Skip to content

回文自动机求双倍回文 ​

cpp
struct PAM{
	static constexpr int ALPHABET_SIZE=26;
	struct Node{
		int len,link,cnt;// cnt表示以当前字符结尾的不同子串个数(视实际情况而定)
		int trans;// 第一个长度小于等于一半的后缀
		array<int,ALPHABET_SIZE> next;
	};
	vector<Node> t;
	int suff;
	string s;
	PAM(){
		init();
	}
	void init(){
		t.assign(2,Node());//0为奇根,1为偶根
		t[0].len=-1;
		suff=1;
		s.clear();
	}
	int newNode(){
		t.emplace_back();
		return t.size()-1;
	}
	bool add(int c){
		int pos=s.size();
		s+=c;
		c=c-'a';
		int cur=suff,curlen=0;
		while(true){
			curlen=t[cur].len;
			if(pos-1-curlen>=0&&s[pos-1-curlen]==s[pos])break;
			cur=t[cur].link;
		}
		if(t[cur].next[c]){
			suff=t[cur].next[c];
			return false;
		}
		suff=newNode();
		t[suff].len=t[cur].len+2;
		t[cur].next[c]=suff;
		if(t[suff].len==1){
			t[suff].link=1;
			t[suff].trans=1;
			return true;
		}
		if(t[suff].len<=2){
			t[suff].trans=t[suff].link;
		}
		else{
			int p=t[cur].trans;
			while(t[p].len+2>t[suff].len/2||s[pos-1-t[p].len]!=s[pos])p=t[p].link;
			t[suff].trans=t[p].next[c];
		}
		while(true){
			cur=t[cur].link;
			curlen=t[cur].len;
			if(pos-1-curlen>=0&&s[pos-1-curlen]==s[pos]){
				t[suff].link=t[cur].next[c];
				break;
			}
		}
		return true;
	}
	int next(int p,int c){
		return t[p].next[c-'a'];
	}
	int link(int p){
		return t[p].link;
	}
	int len(int p){
		return t[p].len;
	}
	int cnt(int p){
		return t[p].cnt;
	}
	int trans(int p){
		return t[p].trans;
	}
	int size(){
		return t.size();
	}
} pam;
void solve(){
	int n;
	cin>>n;
	string s;
	cin>>s;
	auto &t=pam.t;
	for(int i=0;i<s.size();i++){
		pam.add(s[i]);
	}
	int ans=0;
	for(int i=2;i<t.size();i++){
		if(pam.len(pam.trans(i))*2==pam.len(i)&&pam.len(i)%4==0)ans=max(ans,pam.len(i));
	}
	cout<<ans<<"\n";
}