Skip to content

回文自动机 ​

  • 本质不同回文串个数=状态数-2
cpp
struct PAM{
	static constexpr int ALPHABET_SIZE=26;
	struct Node{
		int len,link,cnt;// cnt表示以当前字符结尾的不同子串个数(视实际情况而定)
		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].cnt=1;
			return true;
		}
		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;
			}
		}
		t[suff].cnt=1+t[t[suff].link].cnt;
		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 size(){
		return t.size();
	}
} pam;