字符串例题

1.kmp

#include<iostream>
using namespace std;
string a,b;
int ne[1000010];
int main()
{
	cin>>a>>b;
	int n=a.size(),m=b.size();
	a=' '+a,b=' '+b;
	for(int i=2,j=0;i<=m;i++){
		while(j&&b[i]!=b[j+1])j=ne[j];
		if(b[i]==b[j+1])j++;
		ne[i]=j;
	}
	for(int i=1,j=0;i<=n;i++){
		while(j&&a[i]!=b[j+1])j=ne[j];
		if(a[i]==b[j+1])j++;
		if(j==m){
            printf("%d\n",i-m+1);
			j=ne[j];
		}
	}
	for(int i=1;i<=m;i++)printf("%d ",ne[i]);
	return 0;
}

2.hash

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10;

int main()
{
	int n,q; cin>>n>>q;
	string s; cin>>s;

	while(q--)
	{
		string t; cin>>t;

		int ok=1,pre=-1;
		for(int i=0;i<t.size();i++)
		{
			if(s.find(t[i],pre+1)==s.npos)
			{
				ok=0;
				break;
			}
			pre=s.find(t[i],pre+1);
		}
		if(ok) puts("YES");
		else puts("NO");
	}

	return 0;
}

 

#include <bits/stdc++.h>
#define ll long long
#define mod 998244353
using namespace std;
const int N=2e5+7;
string s1,s2;
int p1[N],p2[N],n;
void manacher(string &s,int p[]){
	string str="$#";
	for(int i=0;i<n;i++){
//		str=str+s[i]+'#';
		str+=s[i];
		str+='#';
	}
	int len=str.length();
	int mx=0,id=0;
	for(int i=1;i<len;i++){
		if(i<mx) p[i]=min(mx-i,p[2*id-i]);
		else p[i]=1;
		while(str[i+p[i]]==str[i-p[i]]) p[i]++;
		if(i+p[i]>mx){
			mx=i+p[i];
			id=i;
		}
	}
	s=str;
}


int main(){
	cin>>n;
	cin>>s1>>s2;
	manacher(s1,p1);
	manacher(s2,p2);
	int len=s1.length(),ans=1;
	for(int i=2;i<len;i++){
		int x=max(p1[i],p2[i-2]);
		while(s1[i-x]==s2[i-2+x]) x++;
		ans=max(ans,x);
	}
	printf("%d\n",ans-1);
}

#include<bits/stdc++.h>
using namespace std;
#define N 400020
#define LL long long
LL n,q,r[N],s[N],L,R,m,mx,id,ans[N],a[N],b[N],sl[N],sr[N];
vector<LL>dl[N],dr[N];
vector<pair<LL,LL>>ql[N],qr[N];
struct BIT
{
	LL t[2][N];
	LL lowbit(LL x){return x&(-x);}
	void cg(LL o,LL x,LL c){while(x<N)t[o][x]+=c,x+=lowbit(x);}
	LL ask(LL o,LL x){LL r=0;while(x)r+=t[o][x],x-=lowbit(x);return r;}
	LL ask(LL o,LL l,LL r){return ask(o,r)-ask(o,l-1);}
	LL query(LL k,LL l,LL r){return ask(0,l,r)+k*ask(1,l,r);}
}tl,tr;
int main()
{
	scanf("%lld%lld",&n,&q);
	for(LL i=1;i<=n;i++){
		char ch=getchar();
		while(ch<'a' || ch>'z')ch=getchar();
		s[i*2-1]=ch-'a'+1;
		s[i*2]=27;
	}
	n=n*2-1,s[0]=27;
	for(LL i=1;i<=n;i++){
		r[i]=1;
		if(mx>i)r[i]=min(r[2*id-i],mx-i+1);
		while(0<=i-r[i] && i+r[i]<=n+1 && s[i+r[i]]==s[i-r[i]])r[i]++;
		if(i+r[i]-1>mx)mx=i+r[i]-1,id=i;
	}
	for(LL i=1;i<=n;i++){
		r[i]=r[i]/2;
		if(i&1)a[i]=r[i]-i/2-1;else a[i]=r[i]-i/2;
		b[i]=r[i]+i/2-1;
		if(a[i]>=0)a[i]=0,tl.cg(1,i,1);
		else dl[-a[i]*2].push_back(i),tl.cg(0,i,a[i]);
		if(b[i]>=(n+1)/2)b[i]=(n+1)/2,tr.cg(1,i,1);
		else dr[b[i]*2].push_back(i),tr.cg(0,i,b[i]);
		sl[i]=sl[i-1]+(i&1?i/2+1:i/2);
		sr[i]=sr[i-1]+(1-i/2);
	}
	for(LL i=1;i<=q;i++){
		scanf("%lld%lld",&L,&R);
		m=L+R-1,L=L*2-1,R=R*2-1;
		ans[i]+=sl[m]-sl[L-1]+sr[R]-sr[m];
		ql[L].push_back(make_pair(i,m));
		qr[R].push_back(make_pair(i,m));
	}
	for(LL i=1;i<=n;i++){
		for(auto j:dl[i])tl.cg(0,j,-a[j]),tl.cg(1,j,1);
		for(auto pi:ql[i])ans[pi.first]+=tl.query(-i/2,i,pi.second);
	}
	for(LL i=n;i>=1;i--){
		for(auto j:dr[i])tr.cg(0,j,-b[j]),tr.cg(1,j,1);
		for(auto pi:qr[i])ans[pi.first]+=tr.query(i/2,pi.second+1,i);
	}
	for(LL i=1;i<=q;i++)printf("%lld\n",ans[i]);
}

#include <bits/stdc++.h>
using namespace std;

const int N = 5e5 + 10;
char s[N];
int len[N], cnt[N][2], fail[N];
int t[N][26], last = 0, tot = 1;

int getfail(int u, int p)
{
	while (s[p - len[u] - 1] != s[p]) u = fail[u];
	return u;
}

void insert(int c, int p, int id)
{
	int u = getfail(last, p);
	if (!t[u][c])
	{
		fail[++tot] = t[getfail(fail[u], p)][c];
		len[t[u][c] = tot] = len[u] + 2;
	}
	cnt[last = t[u][c]][id]++;
}

int main()
{
	fail[0] = 1, s[0] = '!', len[1] = -1;
	scanf("%s", s + 1);
	for (int i = 1; s[i]; i++) insert(s[i] - 'A', i, 0);
	scanf("%s", s + 1), last = 0;
	for (int i = 1; s[i]; i++) insert(s[i] - 'A', i, 1);
	for (int i = tot; i > 1; i--)
		cnt[fail[i]][0] += cnt[i][0], cnt[fail[i]][1] += cnt[i][1];
	long long ans = 0;
	for (int i = 2; i <= tot; i++) ans += 1ll * cnt[i][0] * cnt[i][1];
	cout << ans;
	return 0;
}

3.border树,trie树

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int n,idx;
bool cnt[300010];
string s[30010];
int tr[300010][26];
vector<string>q;
void insert(string s)
{
	int u=0;
	for(int i=0;i<s.size();i++){
		int p=s[i]-'a';
		if(!tr[u][p])tr[u][p]=++idx;
		u=tr[u][p];
	}
	cnt[u]=true;
}
bool check(string s)
{
	int u=0;
	int in[26]={0};
	vector<int>edge[26];
	for(int i=0;i<s.size();i++){
		if(cnt[u])return false;
		int p=s[i]-'a';
		for(int j=0;j<26;j++){
			if(p!=j&&tr[u][j]){
				in[j]++;
				edge[p].push_back(j);
			}
		}
		u=tr[u][p];
	}
	queue<int>Q;
	for(int i=0;i<26;i++){
		if(in[i]==0)Q.push(i);
	}
	while(Q.size()){
		int t=Q.front();
		Q.pop();
		for(auto c:edge[t]){
			in[c]--;
			if(in[c]==0)Q.push(c);
		}
	}
	for(int i=0;i<26;i++){
		if(in[i])return false;
	}
	return true;
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>s[i];
		insert(s[i]);
	}
	for(int i=1;i<=n;i++){
		if(check(s[i]))q.push_back(s[i]);
	}
	cout<<(int)q.size()<<endl;
	for(auto c:q)cout<<c<<endl;
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
const int N = 3e6+50; 
int ch[N][2],tot;
void insert(int x){
	int u=0;
	for(int i=30;~i;i--){
		int v=(x>>i)&1;
		if(!ch[u][v]) ch[u][v]=++tot;
		u=ch[u][v];
	}
}
int query(int x){
	int res=0,u=0;
	for(int i=30;~i;i--){
		int v=(x>>i)&1;
		if(ch[u][v^1]) v^=1,res|=1<<i;
		u=ch[u][v];
	}
	return res;
}
signed main(void){
	ios::sync_with_stdio(false);cin.tie(0);
	int n,res=0,x;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x;
		res=max(res,query(x));
		insert(x);
	}
	cout<<res;
}

#include<bits/stdc++.h>
using namespace std;
int t[100010*32][2],idx,cnt[100010*32],id;
void insert(int x){
	int now=0;
	for(int i=31;i>=0;i--){
		if(!t[now][x>>i&1])t[now][x>>i&1]=++idx;
		now=t[now][x>>i&1];
	}
	cnt[now]=++id;
}
pair<int,int>ch(int x){
	int ans=0,now=0;
	for(int i=31;i>=0;i--){
		int num=x>>i&1;
		if(t[now][!num])now=t[now][!num],ans+=1<<i;
		else now=t[now][num];
	}
	return {ans,cnt[now]};
}
int a[100100];
int main(){
	int n,ans=-1,l,r;
	cin>>n;
	insert(0);
	for(int i=1;i<=n;i++){
		cin>>a[i];
		a[i]^=a[i-1];
		auto [x,y]=ch(a[i]);
		if(x>ans){
			ans=x;
			l=y,r=i;
		}
		insert(a[i]);
	}
	
	cout<<ans<<" "<<l<<" "<<r<<endl;
	return 0;
}

#include<iostream>
#include<cstring>
using namespace std;
const int N=6e5+5,M=N*25,pos=23;
int n,m;
int s[N];
int tr[M][2],max_id[M];
int root[N],idx;
void insert(int k,int p,int q)
{
	for(int i=pos;i>=0;i--)
	{
		int u=s[k]>>i&1;
		if(p)
		tr[q][u^1]=tr[p][u^1];
		tr[q][u]=++idx;
		p=tr[p][u],q=tr[q][u];
		max_id[q]=k;
	}
}
int query(int root,int c,int l)
{
	int p=root;
	for(int i=pos;i>=0;i--)
	{
		int u=c>>i&1;
		if(max_id[tr[p][u^1]]>=l)
		p=tr[p][u^1];
		else
		p=tr[p][u];
	}
	return c^s[max_id[p]];
}

int main()
{
	cin>>n>>m;
	max_id[0]=-1;
	root[0]=++idx;
	insert(0,0,root[0]);
	for(int i=1;i<=n;i++)
	{
		int x;
		cin>>x;
		s[i]=s[i-1]^x;
		root[i]=++idx;
		insert(i,root[i-1],root[i]);
	}
	char op;
	int l,r,x;
	while(m--)
	{
		cin>>op;
		if(op=='A')
		{
			cin>>x;
		    n++;
		    s[n]=s[n-1]^x;
		    root[n]=++idx;
		    insert(n,root[n-1],root[n]);
		}
		else
		{
			cin>>l>>r>>x;
			cout<<query(root[r-1],s[n]^x,l-1)<<endl;
		}
	}
	return 0;
}

#include<iostream>
using namespace std;
const int N=2e6;
char str[N];
int n,k,nx[N];
int sz[N];
int main()
{
    scanf("%d%d",&n,&k);
    scanf("%s",str+1);
    for(int i=2,j=0;i<=n;i++)
    {
        while(j&&str[j+1]!=str[i]) j=nx[j];
        if(str[j+1]==str[i]) j++;
        nx[i]=j;
    }
    for(int i=n;i>=1;i--)
    {
        sz[i]++;
        sz[nx[i]]+=sz[i];
    }
    int u=n;
    while(sz[u]<k)
    {
        u=nx[u];
    }
    if(u==0) cout<<"-1"<<endl;
    else for(int i=1;i<=u;i++) cout<<str[i];
    return 0;
}

4. ac自动机

#include<bits/stdc++.h>
using namespace std;


template<typename T>std::istream&operator>>(std::istream&is,std::vector<T>&t){for(auto&x:t)is>>x;return is;}
template<typename T>std::ostream&operator<<(std::ostream&os,const std::vector<T>&t){for(int i=0;i<t.size();++i)os<<t[i]<<" \n"[i==t.size()-1];return os;}
#define INF 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl "\n"
#define rep(pigstar,a,b) for (int pigstar = (a); pigstar <= (b); pigstar ++)
#define per(pigstar,a,b) for (int pigstar = (a); pigstar >= (b); pigstar --)
#define cinint(pigstar,a,b) for (int i = (a); i <= (b); i ++) cin >> pigstar[i];
#define coutint(pigstar,a,b) for (int i = (a); i <= (b); i ++) cout << pigstar[i] << " \n"[i==b]
#define all(pigstar) pigstar.begin(),pigstar.end()
#define rvs(pigstar) reverse(pigstar.begin(),pigstar.end())
#define PII array<int, 2>
#define VI vector<int>
#define VPII vector<PII>
#define pb push_back
#define SZ(pigstar) ((int)(pigstar).size())
#define MP make_pair
#define x first
#define y second


#define CN puts("NO")
#define CY puts("YES")

typedef double db;
typedef long long ll;
typedef unsigned long long ull;


//----------------debug---------------//
#define debug(args...) { string _s = #args; auto end_pos = remove(_s.begin(), _s.end(), ' '); _s.erase(end_pos, _s.end()); replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); cout << "\n";}
void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
    cerr << (*it) << " = " << a << "   ";
    err(++it, args...);
}
//----------------debug---------------//

//----------------hash_map---------------//
#include <functional>
template <typename T>
inline void hash_combine(std::size_t &seed, const T &val) {
    seed ^= std::hash<T>()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
// auxiliary generic functions to create a hash value using a seed
template <typename T> 
inline void hash_val(std::size_t &seed, const T &val) {
    hash_combine(seed, val);
}
template <typename T, typename... Types>
inline void hash_val(std::size_t &seed, const T &val, const Types &... args) {
    hash_combine(seed, val);
    hash_val(seed, args...);
}
 
template <typename... Types>
inline std::size_t hash_val(const Types &... args) {
    std::size_t seed = 0;
    hash_val(seed, args...);
    return seed;
}
 
struct pair_hash {
    template <class T1, class T2>
    std::size_t operator()(const std::pair<T1, T2> &p) const {
        return hash_val(p.first, p.second);
    }
};
struct int_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
 
    size_t operator()(const uint64_t x) const {
        static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};
//unordered_map<PII,int,pair_hash> mp1
// unordered_map<int,int,int_hash> mp2
//----------------hash_map---------------//





const int maxn = 2e6+7;
const int mod = 1e9+7;
const double eps = 1e-7;

int qmi(int a, int k, int p){int res = 1;while (k){if (k & 1) res = (ll)res * a % p;a = (ll)a * a % p;k >>= 1;}return res;}
int qpow(int a,int b){int res = 1;while(b){if(b&1) res *= a;b>>=1;a*=a;}return res;}
int mo(int x,int p){return x = ((x%p)+p)%p;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lowbit(int x) { return (-x)&x; }
int fac[maxn], invfac[maxn], __ = [] {
    fac[0] = 1;
    for (int i = 1; i < maxn; i ++) {
        fac[i] = (fac[i - 1] * i) % mod;
    }
    invfac[maxn - 1] = qmi(fac[maxn - 1], mod - 2, mod);
    for (int i = maxn - 1; i; i --) {
        invfac[i - 1] = (invfac[i] * i) % mod;
    }
    return 0;
}();
int C (int n, int m) {
    return ((fac[n] * invfac[m]) % mod * invfac[n - m]) % mod;
}


int dx[] = {0,0,1,-1}, dy[] = {1,-1,0,0};

int T = 1,N,M,K,Q;
// unordered_map<PII,int,pair_hash> mp;
// unordered_map<int,int,int_hash> mp2;

struct AC_Automaton{
    int nxt[maxn][26], fail[maxn], cnt[maxn], id[maxn];
    int root, idx;
    vector<int>g[maxn];//用来保存最后的fail的树
    
    void clear(){
        memset(nxt[0],0,sizeof(nxt[0]));
        root = idx = 0;
    }
    int newnode(){
        idx++; memset(nxt[idx],0,sizeof(nxt[idx]));
        return idx;
    }
    int insert(int pre, int ch){
        return nxt[pre][ch]?nxt[pre][ch]: nxt[pre][ch] = newnode();
    }
    int insert(string s, int u){
        int now = root;
        for(char &c : s){
            now = insert(now, c-'a');
        }
        return id[u] = now;
    }
    void build(){
        fail[root] = root;
        queue<int>q;
        for(int i = 0 ; i < 26 ; i ++) {
            if(nxt[0][i]) {
                g[0].push_back(nxt[0][i]);
                q.push(nxt[0][i]);
            }
        }
        while(!q.empty()){
            int h = q.front(); q.pop();
            for(int i = 0 ; i < 26 ; i ++){
                if(!nxt[h][i]){
                    nxt[h][i] = nxt[fail[h]][i];
                }
                else{
                    int tmp = nxt[h][i];
                    fail[tmp] = nxt[fail[h]][i];
                    g[fail[tmp]].push_back(tmp);
                    q.push(tmp);
                }
            }
        }
    }
    void query(string &s){
        int now = root;
        for(char &c : s){
            now = nxt[now][c-'a'];
            cnt[now]++;
        }
        get_ans();
    }
    void get_ans() {
        for (int i = 0; i < 26; i++)
            if (nxt[0][i])dfs(nxt[0][i]);
    }

    void dfs(int u) {
        for (int v : g[u]) {
            dfs(v);
            cnt[u] += cnt[v];
        }
    }
}ac;

string s,t;
void solve(){
    cin >> N;
    for (int i = 0; i < N; i ++) {
        cin >> t;
        ac.insert(t,i);
    }
    ac.build();
    cin >> s;
    ac.query(s);
    rep(i,0,N-1) {
        cout << ac.cnt[ac.id[i]] << endl;
    }
    
    
    
    
    
}
signed main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    cout.setf(ios::fixed);cout.precision(16);
    // cin >> T;
    // fact_init();
    while (T --) {
        solve();
    }
    return (0-0); //<3
} 

//最简ac自动机
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int N=2e5+3;
int t[N][26],cnt,fail[N],stop[N],ans[N],id[N];
void insert(string s,int p){
    int x=0;
    for(auto& i:s){
        int k=i-'a';
        if(!t[x][k])t[x][k]=++cnt;
        x=t[x][k];
    }
    stop[x]++;id[p]=x;
}
int q[N],top=0,low=1;
void bfs(){
    rep(i,0,25)if(t[0][i])q[++top]=t[0][i];
    while(low<=top){
        int x=q[low++];
        rep(i,0,25){
            int & son=t[x][i];
            if(son){
                fail[son]=t[fail[x]][i];q[++top]=son;
            }else son=t[fail[x]][i];
        }
    }
}
void query(string s){
    int x=0;
    for(auto& i:s){
        int k=i-'a';
        x=t[x][k];ans[x]++;
    }
    for(int i=top;i>0;i--){
        ans[fail[q[i]]]+=ans[q[i]];
    }
}
int main(){
    int n;cin>>n;
    string s;
    rep(i,1,n)cin>>s,insert(s,i);
    bfs();cin>>s;query(s);
    rep(i,1,n)cout<<ans[id[i]]<<endl;
}

5.pam manacher

//#只会是奇数,字母只会是偶数
//所以两者的长度都是减去1,没错了
#include <bits/stdc++.h>
using namespace std;
const int M=2e5+10;

int cnt=1;
char s[M];
int p[M],L[M],R[M];
void manacher(string t) {
    s[0]='@';
    s[1]='#';
    for(auto i:t)s[++cnt]=i,s[++cnt]='#';
    for(int i=1,mid=0,r=0;i<=cnt;i++) {
        if(i<=r)p[i]=min(p[2*mid-i],r-i+1);
        while(s[i-p[i]]==s[i+p[i]])p[i]++;
        if(i+p[i]>r)r=i+p[i]-1,mid=i;
        L[i+p[i]-1]=max(L[i+p[i]-1],p[i]-1);
        R[i-p[i]+1]=max(R[i-p[i]+1],p[i]-1);
    }
}

int main() {
    string t;cin>>t;
    manacher(t);
    for(int i=3;i<=cnt;i+=2)R[i]=max(R[i],R[i-2]-2);
    for(int i=cnt;i>=1;i-=2)L[i]=max(L[i],L[i+2]-2);
    int ans=0;
    for(int i=3;i<cnt;i++)ans=max(ans,L[i]+R[i]);
    cout<<ans;
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
char s[1000010]={'?'};
int p[1000010],n,ans;
void manacher(char *s,int n){
    for(int c=0,mx=0,i=1;i<=n;i++){
        p[i]=i<mx?min(p[2*c-i],mx-i):1;
        while(s[i+p[i]]==s[i-p[i]])++p[i];
        if(i+p[i]>mx){
        	if(i&1)for(int j=max(mx,i+4);j<i+p[i];j++)
				if(!(j-i&3) && p[i-(j-i)/2]>(j-i)/2)ans=max(ans,j-i);
			mx=i+p[i],c=i;
		}
    }
}
int main(){
	scanf("%d %s",&n,s+1);
    for(int i=n;i;i--)s[i*2+1]='#',s[i*2]=s[i];s[1]='#';
    manacher(s,2*n+1);
    printf("%d\n",ans);
    return 0;
}
// o队的代码,我改了改
#include <bits/stdc++.h>
using namespace std;
#define fo(i,j,k) for(int i=(j),end_i=(k);i<=end_i;i++)
#define ff(i,j,k) for(int i=(j),end_i=(k);i< end_i;i++)
#define fd(i,j,k) for(int i=(j),end_i=(k);i>=end_i;i--)
#define DEBUG(x) cerr<<#x<<"="<<x<<endl
#define DEBUGv(x) cerr<<#x<<" : "; ff(i,0,(x).size()) cerr<<(x)[i]<<(i==(x).size()-1?'\n':' ')
#define all(x) (x).begin(),(x).end()
#define cle(x) memset(x,0,sizeof(x))
#define lowbit(x) ((x)&-(x))
#define VI vector<int>
#define ll long long
#define ull unsigned ll
#define lll __int128
#define db double
#define lb long db
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define endl "\n"
template<class T>inline void read(T &x) {
    x=0; char ch=getchar(); bool f=0;
    for(;ch<'0'||ch>'9';ch=getchar()) f|=(ch=='-');
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+(ch^48);
    if(f) x=-x;
}
template<class T, class... V>
inline void read(T &a, V&... b){read(a); read(b...);}
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());

const int N = 5e5 + 5;
const int S = 26;

namespace PAM {
	int n,s[N],num[N],p,las,nex[N][S],fail[N],len[N],sz[N];
    ll ans;
    int cnt[N];
    int f[N][19];
    int ans2; 
    
    void add(int x, int y) {
        cnt[y] = cnt[x];
        int cha=len[y]-len[x];
        if(len[y]%4==0 && (len[y]/2)%cha==0 && cha<=len[y]/2 && y>=3) 
		{
			cnt[y]++;
			ans2=max(len[y],ans2);
		}
    }
	void init() {
        ans = 0;
        ans2 = 0;
		for(int i=0;i<=n;i++) s[i]=0;
		for(int i=1;i<=p;i++) len[i]=fail[i]=sz[i]=0,memset(nex[i],0,sizeof(nex[i])),memset(f[i],0,sizeof(f[i])), cnt[i]=0;
		s[n=0]=len[p=2]=-1;
		fail[las=1]=fail[2]=2;
        len[1]=0;
        add(2,0);
        add(2,1);
	}
	int getfail(int x) {for(;s[n-1-len[x]]!=s[n];x=fail[x]); return x;}
    void update(int x) {
        ans += cnt[x];
    }
	void add(int c) {
		s[++n]=c;
		int cur=getfail(las);
		if(!nex[cur][c]) {
			len[++p]=len[cur]+2;
			fail[p]=nex[getfail(fail[cur])][c];
			if(!fail[p]) fail[p]=1;
			nex[cur][c]=p;
            add(fail[p], p);
		}
		las=nex[cur][c];
		sz[las]++;
        update(las);
	}
    ll ask() {
        return ans2;
    }
}
char s[N];
void Solve() {
    PAM::init();
    scanf("%s", s + 1);
    int n = strlen(s + 1);
    fo(i,1,n) {
        PAM::add(s[i] - 'a');
    }
    printf("%d\n", PAM::ask());
}
int main() {
    int T = 1;
    int n;
    read(n);
    for(;T--;) Solve();
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
typedef long long ll;
char s[N];
int n,last,len[N];
int now,tot=1,fail[N],cnt[N],trie[N][30];
int getfail(int u,int p)
{
    while(p-len[u]-1<=0||s[p-len[u]-1]!=s[p]) u=fail[u];
    return u;
}
void insert(char c,int id)
{
    int p=getfail(now,id);
    
    if(!trie[p][c-'a'])
    {
        fail[++tot]=trie[getfail(fail[p],id)][c-'a'];
        
        trie[p][c-'a']=tot;
        len[tot]=len[p]+2;
    }
    now=trie[p][c-'a'];
    cnt[now]++;
}
int main()
{
    cin>>n>>s+1;
    fail[0]=1;
    len[1]=-1;
    for(int i=1;i<=n;i++) insert(s[i],i);
    for(int i=tot;i>=1;i--) cnt[fail[i]]+=cnt[i];
    ll ans=0;
    for(int i=1;i<=tot;i++)
    {
        ans=max(ans,1ll*cnt[i]*len[i]);
    }
    cout<<ans<<endl;
}

#include <bits/stdc++.h>
using namespace std;
#define fo(i,j,k) for(int i=(j),end_i=(k);i<=end_i;i++)
#define ff(i,j,k) for(int i=(j),end_i=(k);i< end_i;i++)
#define fd(i,j,k) for(int i=(j),end_i=(k);i>=end_i;i--)
#define DEBUG(x) cerr<<#x<<"="<<x<<endl
#define DEBUGv(x) cerr<<#x<<" : "; ff(i,0,(x).size()) cerr<<(x)[i]<<(i==(x).size()-1?'\n':' ')
#define all(x) (x).begin(),(x).end()
#define cle(x) memset(x,0,sizeof(x))
#define lowbit(x) ((x)&-(x))
#define VI vector<int>
#define ll long long
#define ull unsigned ll
#define lll __int128
#define db double
#define lb long db
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define endl "\n"
template<class T>inline void read(T &x) {
    x=0; char ch=getchar(); bool f=0;
    for(;ch<'0'||ch>'9';ch=getchar()) f|=(ch=='-');
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+(ch^48);
    if(f) x=-x;
}
template<class T, class... V>
inline void read(T &a, V&... b){read(a); read(b...);}
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 3e5 + 5;
const int S = 26;
namespace PAM {
	int n,s[N],num[N],p,las,nex[N][S],fail[N],len[N],sz[N];
	ll ans; 
	void init() {
		ll ans=0;
		for(int i=0;i<=n;i++) s[i]=0;
		for(int i=1;i<=p;i++) len[i]=fail[i]=sz[i]=0,memset(nex[i],0,sizeof(nex[i]));
		s[n=0]=len[p=2]=-1;
		fail[las=1]=fail[2]=2;
        len[1]=0;
	}
	int getfail(int x) {for(;s[n-1-len[x]]!=s[n];x=fail[x]); return x;}
	void add(int c) {
		s[++n]=c;
		int cur=getfail(las);
		if(!nex[cur][c]) {
			len[++p]=len[cur]+2;
			fail[p]=nex[getfail(fail[cur])][c];
			if(!fail[p]) fail[p]=1;
			nex[cur][c]=p;
		}
		las=nex[cur][c];
		sz[las]++;
		//cout<<las<<' '<<sz[las]<<' '<<len[las]<<endl;
		//ans=max(ans,1ll*sz[las]*len[las]);
	}
	void cnt()
	{
		for(int i=p;i>=3;i--)
		{
			sz[fail[i]]+=sz[i];
			ans=max(ans,1ll*sz[i]*len[i]);
		}
	}	
	ll ask()
	{
		return ans;
	}
}
char s[N];
void Solve() {
    PAM::init();
    scanf("%s", s + 1);
    int n = strlen(s + 1);
    fo(i,1,n) {
        PAM::add(s[i] - 'a');
    }
    PAM::cnt();
    //printf("%lld%c", PAM::ask(),(i==n)?'\n':' ');
    printf("%lld\n",PAM::ask());
}
int main() {
    int T = 1;
    int n;
    
	read(n);
    for(;T--;) Solve();
    return 0;
}

#include <bits/stdc++.h>
using namespace std;

const int N = 5e5 + 10;
char s[N];
int len[N], cnt[N], fail[N];
int t[N][26], last = 0, tot = 1;

int getfail(int u, int p)
{
	while (s[p - len[u] - 1] != s[p]) u = fail[u];
	return u;
}

int f[N]; 
void insert(int c, int p)
{
	int u = getfail(last, p);
	if (!t[u][c])
	{
		fail[++tot] = t[getfail(fail[u], p)][c];
		len[t[u][c] = tot] = len[u] + 2;
		f[tot] = f[u] | (1 << c);
	}
	cnt[last = t[u][c]]++;
}

int calc(int x)
{
	int ans = 0;
	while (x) ans += x & 1, x >>= 1;
	return ans;
}
int main()
{
	fail[0] = 1, s[0] = '!', len[1] = -1;
	scanf("%s", s + 1);
	for (int i = 1; s[i]; i++) insert(s[i] - 'a', i);
	for (int i = tot; i > 1; i--) cnt[fail[i]] += cnt[i];
	long long ans = 0;
	for (int i = 2; i <= tot; i++) ans += 1ll * calc(f[i]) * cnt[i];
	cout << ans;
	return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define fo(i,j,k) for(int i=(j),end_i=(k);i<=end_i;i++)
#define ff(i,j,k) for(int i=(j),end_i=(k);i< end_i;i++)
#define fd(i,j,k) for(int i=(j),end_i=(k);i>=end_i;i--)
#define DEBUG(x) cerr<<#x<<"="<<x<<endl
#define DEBUGv(x) cerr<<#x<<" : "; ff(i,0,(x).size()) cerr<<(x)[i]<<(i==(x).size()-1?'\n':' ')
#define all(x) (x).begin(),(x).end()
#define cle(x) memset(x,0,sizeof(x))
#define lowbit(x) ((x)&-(x))
#define VI vector<int>
#define ll long long
#define ull unsigned ll
#define lll __int128
#define db double
#define lb long db
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define endl "\n"
template<class T>inline void read(T &x) {
    x=0; char ch=getchar(); bool f=0;
    for(;ch<'0'||ch>'9';ch=getchar()) f|=(ch=='-');
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+(ch^48);
    if(f) x=-x;
}
template<class T, class... V>
inline void read(T &a, V&... b){read(a); read(b...);}
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int N = 3e5 + 5;
const int S = 26;
namespace PAM {
	int n,s[N],num[N],p,las,nex[N][S],fail[N],len[N],sz[N];
	int yh[N][30],cnt[N];
	ll ans; 
	void init() {
		ll ans=0;
		for(int i=0;i<=n;i++) s[i]=0;
		for(int i=1;i<=p;i++) len[i]=fail[i]=sz[i]=0,memset(nex[i],0,sizeof(nex[i]));
		s[n=0]=len[p=2]=-1;
		fail[las=1]=fail[2]=2;
        len[1]=0;
	}
	int getfail(int x) {for(;s[n-1-len[x]]!=s[n];x=fail[x]); return x;}
	void yh1(int x,int y,int c)
	{
		for(int i=0;i<=26;i++)
		yh[y][i]=yh[x][i];
		cnt[y]=cnt[x];
		if(yh[y][c]==0)
		{
			cnt[y]++;
			yh[y][c]=1;
		}
	}
	void add(int c) {
		s[++n]=c;
		int cur=getfail(las);
		if(!nex[cur][c]) {
			len[++p]=len[cur]+2;
			fail[p]=nex[getfail(fail[cur])][c];
			if(!fail[p]) fail[p]=1;
			nex[cur][c]=p;
			yh1(cur,p,c);	
		}
		las=nex[cur][c];
		sz[las]++;
	}	
	void cnt1()
	{
		for(int i=p;i>=3;i--)
		{
			sz[fail[i]]+=sz[i];
			ans+=1ll*sz[i]*cnt[i];
		}
	}	
	ll ask()
	{
		return ans;
	}
}
char s[N];
void Solve() {
    PAM::init();
    scanf("%s", s + 1);
    int n = strlen(s + 1);
    fo(i,1,n) {
        PAM::add(s[i] - 'a');
    }
    PAM::cnt1();
    //printf("%lld%c", PAM::ask(),(i==n)?'\n':' ');
    printf("%lld\n",PAM::ask());
}
int main() {
    int T = 1;
    int n;
    
	//read(n);
    for(;T--;) Solve();
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6+10,MOD=1e9+7;
int n,f[N],i,ft[N];
char s[N];
int tr[N][26],fail[N],len[N],g[N],diff[N],slink[N];
int getfail(int u){
	while(i-1-len[u]<=0||s[i-1-len[u]]!=s[i])u=fail[u];
	return u;
}
void work(){
	for(int i = 1;i<=n;++i)f[i]=ft[i],ft[i]=0;
	for(int i = 0;i<=n+5;++i)memset(tr[i],0,sizeof tr[i]),g[i]=0;
	fail[0]=1,len[1]=-1;
	int cnt=1,lst = 0;
	for(i = 1;i<=n;++i){
		int t=s[i]-'a';
		lst=getfail(lst);
		if(!tr[lst][t]){
			fail[++cnt]=tr[getfail(fail[lst])][t];
			tr[lst][t]=cnt;
			len[cnt]=len[lst]+2;
			diff[cnt]=len[cnt]-len[fail[cnt]];
			if(fail[cnt]<=1){
				diff[cnt]=-233;
			}
			if(diff[cnt]!=diff[fail[cnt]]){
				slink[cnt]=cnt;
			}
			else slink[cnt]=slink[fail[cnt]];
		}
		lst=tr[lst][t];
		int u=lst;
		ft[i]=ft[i-1];
		while(u>1){
			if(slink[u]!=u){
				g[u]=max(g[fail[u]]+diff[u],f[i-len[slink[u]]]+len[slink[u]]);
			}
			else{
				g[u]=f[i-len[slink[u]]]+len[slink[u]];
			}
			ft[i]=max(ft[i],g[u]);
			u=fail[slink[u]];
		}
//		cout<<ft[i]<<'\n';
	}
		
}

void solve(){
	scanf("%s",s+1);
	n=strlen(s+1);
	for(int i = 1;i<=n;++i)ft[i]=0;
	work();
	work();
	work();
	cout<<ft[n]<<'\n';
}
int main(){
//	freopen("a.txt","r",stdin);
	int T=1;
	cin>>T;
	while(T--){
		solve();
	}
	
    return 0;
}

6.sa

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int rk[N],sa[N],c[N],id[N],px[N],ht[N];
char s[N];
bool cmp(int x,int y,int w){
	return id[x]==id[y]&&id[x+w]==id[y+w];
}
void init(int n){
	int m=26,p,k,i;
	for(i=0;i<=m;i++) c[i]=0;
	for(i=1;i<=n;i++) c[rk[i]=(s[i]-'a'+1)]++;
	for(i=1;i<=m;i++) c[i]+=c[i-1];
	for(i=n;i>=1;i--) sa[c[rk[i]]--]=i;//
	for(k=1;;k<<=1,m=p){
		for(p=0,i=n;i>n-k;--i)id[++p]=i;
		for(i=1;i<=n;i++)
			if(sa[i]>k)id[++p]=sa[i]-k;
		//将所有的
		for(i=0;i<=m;i++)c[i]=0;
		for(i=1;i<=n;++i) ++c[px[i] = rk[id[i]]];
		for(i=1;i<=m;++i) c[i] += c[i-1];
		for(i=n;i>=1;--i) sa[c[px[i]]--] = id[i];
		for(i=0;i<=n;++i) swap(rk[i],id[i]);
		for(p=0,i=1;i<=n;++i)
			rk[sa[i]]=cmp(sa[i],sa[i-1],k) ? p : ++p;
		if(p>=n) break;
	}
    for(int i=0;i<=n;i++)id[i]=0;
	for(int i=1,k=0;i<=n;i++){
		if(k)k--;
		int j=sa[rk[i]-1];
		while(s[i+k]==s[j+k])k++;
		ht[rk[i]] = k;
	}
}
int main(){
	int t;
	cin>>t;
	while(t--){
		scanf("%s",s+1);
		int n=strlen(s+1);
		init(n);
		for(int i=1;i<=n;i++)cout<<sa[i]<<' ';
			puts("");
		for(int i=1;i<=n;i++)cout<<ht[i]<<' ';
			puts("");
	}
	return 0;
}

#include<bits/stdc++.h>
using namespace std;
int const N=1000000+3;
struct node
{
    int ch[26];
    int len,fa;
    node()
    {
        memset(ch,0,sizeof(ch));
        len=0;
    }
} a[N<<1];
int ls=1,tot=1;
void add(int c)
{
    int p=ls;
    int np=ls=++tot;
    a[np].len=a[p].len+1;
    for(; p&&!a[p].ch[c]; p=a[p].fa) a[p].ch[c]=np;
    if(!p)  a[np].fa=1;
    else
    {
        int q=a[p].ch[c];
        if(a[q].len==a[p].len+1)  a[np].fa=q;
        else
        {
            int nq=++tot;
            a[nq]=a[q];
            a[nq].len=a[p].len+1;
            a[q].fa=a[np].fa=nq;
            for(; p && a[p].ch[c]==q; p=a[p].fa) a[p].ch[c]=nq;
        }
    }
}
char s[N<<1];
int len;
int main()
{
    scanf("%s",s);
    for(int i=0; s[i]; i++) add(s[i]-'a');
    long long ans=0;
    for(int i=1; i<=tot; i++)  ans+=a[i].len-a[a[i].fa].len;
    printf("%lld\n",ans);
    return 0;
}

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

struct node {
	int fa, len;
	int son[31];
	node() {
		fa = len = 0;
		memset(son, 0, sizeof(son));
	}
}d[500001*2];
char a[500001], b[500001];
int an, bn, tot, lst, ans;

void SAM_build(int now) {
	int p = lst;
	int np = ++tot;
	lst = np;
	d[np].len = d[p].len + 1;
	
	for (; p && !d[p].son[now]; p = d[p].fa)
		d[p].son[now] = np;
	
	if (!p) d[np].fa = 1;
		else {
			int q = d[p].son[now];
			if (d[q].len == d[p].len + 1) d[np].fa = q;
				else {
					int nq = ++tot;
					d[nq] = d[q];
					d[nq].len = d[p].len + 1;
					d[q].fa = nq;
					d[np].fa = nq;
					for (; p && d[p].son[now] == q; p = d[p].fa)
						d[p].son[now] = nq;
				}
		}
}

void work() {
	int now = 1, nowd = 0;
	for (int i = 1; i <= bn; i++) {
		int go = b[i] - 'a';
		if (d[now].son[go]) {
			nowd++;
			now = d[now].son[go];
			ans = max(ans, nowd);
			continue;
		}
		while (now && !d[now].son[go]) now = d[now].fa;
		if (!now) {
			nowd = 0;
			now = 1;
		}
		else {
			nowd = d[now].len + 1;
			now = d[now].son[go];
		}
		ans = max(ans, nowd);
	}
}

int main() {
	scanf("%s\n%s", a + 1, b + 1);
	an = strlen(a + 1);
	bn = strlen(b + 1);
	
	tot = 1;
	lst = 1;
	for (int i = 1; i <= an; i++)
		SAM_build(a[i] - 'a');
	
	work();
	
	printf("%d", ans);
	
	return 0;
}

#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<cstring>
#include<vector>
#include<iostream>
#include<string>
#define Inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int MAXX=1000005;

struct SamNode{
	int ch[26];
	int len,fa;
	bool vis[2];
	SamNode(){memset(ch,0,sizeof(ch));len=0;vis[0]=vis[1]=false;}
}sam[MAXX<<1];
int las=1,sam_cnt=1;

void add(int c,int jj){
	int p=las;int np=las=++sam_cnt;
//	num[np]=1LL;//此行为计数用,标记出现过几次 
	sam[np].len=sam[p].len+1;
	for(;p&&!sam[p].ch[c];p=sam[p].fa) sam[p].ch[c]=np;
	if(!p) sam[np].fa=1;
	else{
		int q=sam[p].ch[c];
		if(sam[q].len==sam[p].len+1) sam[np].fa=q;
		else{
			int nq=++sam_cnt;sam[nq]=sam[q];
			sam[nq].len=sam[p].len+1;
			sam[q].fa=sam[np].fa=nq;
			for(;p&&sam[p].ch[c]==q;p=sam[p].fa) sam[p].ch[c]=nq;
		}
	}
	for(;np&&!sam[np].vis[jj];np=sam[np].fa) sam[np].vis[jj]=true;
}

int n;
char s[MAXX];
LL ans=0;

inline void solve(){
	for(int i=1;i<=2;++i){
		scanf("%s",s+1);getchar();
		n=strlen(s+1);
		las=1;
		for(int j=1;j<=n;++j)
			add(s[j]-'a',i-1);
	}
	
	for(int i=1;i<=sam_cnt;++i)
		if(sam[i].vis[0]&&sam[i].vis[1])
			ans+=sam[i].len-sam[sam[i].fa].len;
	
	printf("%lld\n",ans);
}

signed main(){
//	int t;scanf("%d",&t);
//	while(t--)
		solve();
	
	return 0;
}

7.sam

#include<bits/stdc++.h>
using namespace std;
const int N=2000005;
char s[N];
int a[N],c[N],siz[N];
int last,cnt;
int ch[N<<1][26],fa[N<<1],len[N<<1];
void extend(int C)
{
	int p=last,np=++cnt;
	last=np;
	len[np]=len[p]+1;
	for(;p&&!ch[p][C];p=fa[p])ch[p][C]=np;
	if(!p)fa[np]=1;
	else
	{
		int q=ch[p][C];
		if(len[p]+1==len[q])fa[np]=q;
		else
		{
			int nq=++cnt;
			len[nq]=len[p]+1;
			memcpy(ch[nq],ch[q],sizeof(ch[q]));
			fa[nq]=fa[q];
			fa[q]=fa[np]=nq;
			for(;ch[p][C]==q;p=fa[p])ch[p][C]=nq;
		}
	}
	siz[np]=1;
}
void build()
{
	for(int i=1;i<=cnt;i++)c[len[i]]++;
	for(int i=1;i<=cnt;i++)c[i]+=c[i-1];
	for(int i=1;i<=cnt;i++)a[c[len[i]]--]=i;
	for(int i=cnt;i;i--){int p=a[i];siz[fa[p]]+=siz[p];}
}
void solve()
{
	long long ans=0;
	for(int i=1;i<=cnt;i++)if(siz[i]!=1)
		ans=max(ans,1ll*len[i]*siz[i]);
	printf("%lld\n",ans);
}
int main()
{
	scanf("%s",s+1);
	int Len=strlen(s+1);
	last=cnt=1;
	for(int i=1;i<=Len;i++)extend(s[i]-'a');
	build();
	solve();
	return 0;
}
// Template Ver.220713 - StelaYuri
//#pragma GCC optimize(3)
//#include<bits/stdc++.h>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<chrono>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<functional>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<random>
#include<set>
#include<sstream>
#include<stack>
#include<string>
#include<unordered_map>
#include<utility>
#include<vector>
using namespace std;
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
//using namespace __gnu_pbds;
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(auto i=(a);i<=(b);i++)
#define repp(i,a,b) for(auto i=(a);i<(b);i++)
#define per(i,a,b) for(auto i=(a);i>=(b);i--)
#define perr(i,a,b) for(auto i=(a);i>(b);i--)
#define REP(i,a,b,s) for(auto i=(a);i<=(b);i+=(s))
#define REPP(i,a,b,s) for(auto i=(a);i<(b);i+=(s))
#define PER(i,a,b,s) for(auto i=(a);i>=(b);i-=(s))
#define PERR(i,a,b,s) for(auto i=(a);i>(b);i-=(s))
#define all(a) (a).begin(),(a).end()
#define mst(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define eb emplace_back
#define YES cout<<"Yes\n"
#define NO cout<<"No\n"
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
namespace BasicT {
    const int INF=0x3f3f3f3f;
    const ll LINF=0x3f3f3f3f3f3f3f3f;
    const int dx[8]={0,1,0,-1,1,1,-1,-1},dy[8]={1,0,-1,0,1,-1,1,-1};
    const ll mod=998244353;
    mt19937 mtrandom(std::chrono::system_clock::now().time_since_epoch().count());
    template<typename T>T getRandom(T l,T r){return uniform_int_distribution<T>(l,r)(mtrandom);}
    template<typename T>T gcd(T a,T b){return b==0?a:gcd(b,a%b);}
    template<typename T>T qmul(T a,T b){T r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
    template<typename T>T qpow(T a,T n){T r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
    template<typename T>T qpow(T a,T n,T p){T r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}
}
namespace DebugT {
    void debug(){cerr<<'\n';}template<typename T,typename... Args>void debug(T x,Args... args){cerr<<"[ "<<x<< " ] , ";debug(args...);}
    template<typename Ta,typename Tb>istream& operator>>(istream &in,pair<Ta,Tb> &x){in>>x.first>>x.second;return in;}
    template<typename Ta,typename Tb>ostream& operator<<(ostream &out,const pair<Ta,Tb> &x){out<<x.first<<' '<<x.second;return out;}
}
namespace FastIOT {
    const int bsz=1<<18;char bf[bsz],*head,*tail;
    inline char gc(){if(head==tail)tail=(head=bf)+fread(bf,1,bsz,stdin);if(head==tail)return 0;return *head++;}
    template<typename T>inline void read(T &x){T f=1;x=0;char c=gc();for(;!isdigit(c);c=gc())if(c=='-')f=-1;for(;isdigit(c);c=gc())x=x*10+c-'0';x*=f;}
    template<typename T>inline void print(T x){if(x<0)putchar(45),x=-x;if(x>9)print(x/10);putchar(x%10+48);}
    template<typename T>inline void println(T x){print(x);putchar('\n');}
}
using namespace BasicT;
using namespace DebugT;
//using namespace FastIOT;

namespace SAM {
    const int maxc=26;
    const int maxn=1000050;
    int n,
        len[maxn<<1], //最长子串的长度 (该节点子串数量=len[x]-len[link[x]])
        link[maxn<<1], //后缀链接(最短串前部减少一个字符所到达的状态)
        cnt[maxn<<1], //被后缀连接的数
        nex[maxn<<1][maxc], //状态转移(尾部加一个字符的下一个状态)
        idx, //节点编号
        last; //最后节点
    long long epos[maxn<<1], //enpos数(该状态子串出现数量)
              a[maxn]; //长度为i的子串出现最大次数
    void init() {
        last=idx=1; //root起始点
        link[1]=len[1]=0;
    }
    //SAM建图
    void Extend(int c) { //插入字符,为字符ascii码值
        ++n;
        int x=++idx; //创建一个新节点x
        len[x]=len[last]+1; //长度等于最后一个节点+1
        epos[x]=1; //接受节点子串除后缀连接还需加一
        int p; //第一个有C转移的节点
        for(p=last;p&&!nex[p][c];p=link[p])nex[p][c]=x; //沿着后缀连接 将所有没有字符c转移的节点直接指向新节点
        if(!p)link[x]=1,cnt[1]++; //全部都没有c的转移 直接将新节点后缀连接到起点
        else{
            int q=nex[p][c]; //p通过c转移到的节点
            if(len[p]+1==len[q]) //pq是连续的
                link[x]=q,cnt[q]++; //将新节点后缀连接指向q即可 q节点的被后缀连接数+1
            else{
                int nq=++idx; //不连续 需要复制一份q节点
                len[nq]=len[p]+1; //令nq与p连续
                link[nq]=link[q]; //因后面link[q]改变此处不加cnt
                memcpy(nex[nq],nex[q],sizeof(nex[q])); //复制q的信息给nq
                for(;p&&nex[p][c]==q;p=link[p])
                    nex[p][c]=nq; //沿着后缀连接 将所有通过c转移为q的改为nq
                link[q]=link[x]=nq; //将x和q后缀连接改为nq
                cnt[nq]+=2; //nq增加两个后缀连接
            }
        }
        last=x; //更新最后处理的节点
    }
    void GetNpos() { //求npos数,即该节点子串出现次数
        queue<int> q;
        for(int i=1;i<=idx;i++)
            if(!cnt[i])q.push(i); //将所有没被后缀连接指向的节点入队
        while(!q.empty()){
            int x=q.front(); q.pop();
            epos[link[x]]+=epos[x]; //子串数量等于所有后缀连接指向该节点的子串数量和+是否为接受节点
            if(--cnt[link[x]]==0)q.push(link[x]); //当所有后缀连接指向该节点的处理完毕后再入队
        }
    }
    long long GetSubNum() { //求不相同子串数量
        long long ans=0;
        for(int i=2;i<=idx;i++)ans+=len[i]-len[link[i]]; //一状态子串数量等于len[i]-len[link[i]]
        return ans;
    }
    void GetSubMax() { //求出所有长度为k的子串中出现次数最多的子串出现次数
        GetNpos();
        for(int i=1;i<=idx;i++)a[len[i]]=max(a[len[i]],epos[i]); //长度<=k的子串中出现次数最多的子串出现次数的最小值
        for(int i=n-1;i>=1;i--)a[i]=max(a[i],a[i+1]); //求一遍后缀最大值就是答案
    }
}

char str[1000050];

void solve()
{
    SAM::init();
    cin>>(str+1);
    int len=strlen(str+1);
    for(int i=1;i<=len;i++)
        SAM::Extend(str[i]-'a');
    SAM::GetSubMax();
    ll ans=0;
    for(int i=1;i<=len;i++)
        if(SAM::a[i]>1)
            ans=max(ans,1LL*i*SAM::a[i]);
    cout<<ans<<'\n';
}
signed main()
{
    closeSync;
    //multiCase
    {
        solve();
    }
    return 0;
}

#include <iostream>
#include <cstring>
using namespace std;

const int N=200005; // 两倍总串长
int sam[N][26],link[N],len[N];
char s[N],ch[N];
int last,cnt;
int sg[N];

int dfs(int x)
{
	int vis[26]={0};
	if(~sg[x])
		return sg[x];
	for(int i=0; i<26; i++)
		if(sam[x][i])
			vis[dfs(sam[x][i])]=1;
	for(int i=0; i<26; i++)
		if(!vis[i])
			return sg[x]=i;
	return sg[x];
}

void init()
{
	last=cnt=1;
	memset(link,0,sizeof(link));
	memset(sam,0,sizeof(sam));
}

void add(int c)
{
	int p,cur=++cnt;
	len[cur]=len[last]+1;
	for(p=last; p && !sam[p][c]; p=link[p])
		sam[p][c]=cur;
	if(!p)
		link[cur]=1;
	else
	{
		int q=sam[p][c];
		if(len[q]==len[p]+1)
			link[cur]=q;
		else
		{
			int cl=++cnt;
			len[cl]=len[p]+1;
			link[cl]=link[q];
			memcpy(sam[cl], sam[q], sizeof(sam[q]));
			while(p && sam[p][c]==q)
			{
				sam[p][c]=cl;
				p=link[p];
			}
			link[cur]=link[q]=cl;
		}
	}
	last=cur;
}

int main()
{
	while(~scanf("%s", s+1))
	{
		memset(sg,-1,sizeof(sg));
		int lenlen=strlen(s+1);
		init();
		for(int i=1; i<=lenlen; i++)
			add(s[i]-'a');
		int ans=0;
		int n;
		scanf("%d", &n);
		for(int i=1; i<=n; i++)
		{
			scanf("%s", ch+1);
			int len2=strlen(ch+1);
			int p=1;
			for(int j=1; j<=len2; j++)
				p=sam[p][ch[j]-'a'];
			ans^=dfs(p);
		}
		if(ans)
			cout << "Alice" << '\n';
		else
			cout << "Bob" << '\n';
	}
	return 0;
} 

#include<bits/stdc++.h>

using namespace std;
const int N = 5e5 + 10, M = N << 1;
int ch[M][26], len[M], fa[M], np = 1, tot = 1;
vector<int> g[M];
char s[N], t[N];
int now[M];
long long ans;

void extend(int c)
{
	int p = np; np = ++tot;
	len[np] = len[p] + 1;
	while (p && !ch[p][c]) {
		ch[p][c] = np;
		p = fa[p];
	}
	if (!p) {
		fa[np] = 1;
	}
	else {
		int q = ch[p][c];
		if (len[q] == len[p] + 1) {
			fa[np] = q;
		}
		else {
			int nq = ++tot;
			len[nq] = len[p] + 1;
			fa[nq] = fa[q], fa[q] = fa[np] = nq;
			while (p && ch[p][c] == q) {
				ch[p][c] = nq;
				p = fa[p];
			}
			memcpy(ch[nq], ch[q], sizeof ch[q]);
		}
	}
}

void dfs(int u)
{
	for (auto son : g[u]) {
		dfs(son);
		now[u] = max(now[u], now[son]);
	}
	ans += max(0, min(len[u], now[u]) - len[fa[u]]);
}

signed main()
{
	scanf("%s%s", s, t);
	for (int i = 0; s[i]; ++i) {
		extend(s[i] - 'a');
	}
	for (int i = 2; i <= tot; ++i) {
		g[fa[i]].emplace_back(i);
	}
	int p = 1, leng = 0;
	for (int i = 0; t[i]; ++i) {
		int c = t[i] - 'a';
		while (p > 1 && !ch[p][c]) {
			p = fa[p];
			leng = len[p];
		}
		if (ch[p][c]) {
			++leng;
			p = ch[p][c];
		}
		now[p] = max(now[p], leng);
	}
	dfs(1);
	printf("%lld\n", ans);

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值