本文共 1024 字,大约阅读时间需要 3 分钟。
这个一个长得很像AC自动机的自动机回文自动机(PAM)
对于每个点仍然是由转移边,表示每个点的位置向左右各延伸一个字符c,形成的回文串
考虑fail边记录什么,我们主要利用fail去进行加速查找,所以有用的信息是每个位置的最长回文后缀
fail记录每个串的最长回文后缀的左端点,len记录当前位置的回文串长度
设立两个起始节点,0和1,0表示长度为偶数的串的开始,1表示长度为奇数的开始
所以注意赋初值:len[1]=-1 fail[0]=1 tot=1
【题意】
给定一个字符串 s。保证每个字符为小写字母。对于 s 的每个位置,请求出以该位置结尾的回文子串个数。强制在线
【分析】
直接建立回文自动机
然后考虑每个位置结尾的回文子串个数就是沿着fail的深度,直接转移的时候维护一个sum即可
【代码】
#includeusing namespace std;const int maxn=5e5+5;char s[maxn];int tr[maxn][26],len[maxn],cur,tot,last,fail[maxn];int sum[maxn];int getfail(int x,int i){ while(i-len[x]-1<0 || s[i-len[x]-1]!=s[i]) x=fail[x]; return x;}int main(){ freopen("a.in","r",stdin); scanf("%s",s); int l=strlen(s); fail[0]=1; len[1]=-1; tot=1; for(int i=0;i =1) s[i]=(s[i]+last-97)%26+97; int pos=getfail(cur,i); if(!tr[pos][s[i]-'a']) { fail[++tot]=tr[getfail(fail[pos],i)][s[i]-'a']; tr[pos][s[i]-'a']=tot; len[tot]=len[pos]+2; sum[tot]=sum[fail[tot]]+1; } cur=tr[pos][s[i]-'a']; last=sum[cur]; printf("%d ",last); } return 0;}
转载地址:http://bpwm.baihongyu.com/