标签:int manacher len mx fail 自动机 id 回文
manacher
p[i]代表以i为中心的回文串的半径
mx代表当前最长回文串最远的位置
id代表当前最长回文串的中心
将字符串s[0]设为字符'@',在字符串间隔位置插入字符'#'
代码:
scanf("%s", str); int len = strlen(str); for(int i = len ; i >= 0; i --){ str[(i << 1) + 1] = '#'; str[(i << 1) + 2] = str[i]; } str[0] = '@';
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
原串 a b a c a b a
新串 @ # a # b # a # c # a # b # a
核心代码:
void manacher(char *s, int len){ p[0] = 1; int mx = 0 , id = 0; for(int i = 1 ; i < len ; i ++){ p[i] = mx > i ? min(p[id * 2 - i],mx - i) : 1; while(s[i + p[i]] == s[i - p[i]]) p[i] ++; if(i + p[i] > id + p[id]){ id = i; mx = i + p[i]; } } }
当mx>i时,s = id * 2 - i, s与i关于id对称
注意:p[s]可能大于mx - i
当mx<=i时,p[i]直接取1
之后更新id和mx的值
回文自动机
len[p] 记录这个回文串长度
fail[p]记录后缀第二长的回文串的编号
cnt[p]记录这个回文串出现过多少次
规定: fail[0] = 1, len[0] = 0, len[1] = -1
现在有字符串"abaabaa"
虚线为fail指针
初始状态:
第一步:
第二步:
第三步:
第四步:
第五步:
第六步:
第七步没有增加新的点
核心代码:
inline int getfail(int x,int n){ while(s[n-len[x]-1]!=s[n]) x=fail[x]; return x; } void solve(){ for(int i=1;s[i];++i){ s[i]-='a'; p=getfail(last,i); if(!ch[p][s[i]]){ q=newnode(len[p]+2); fail[q]=ch[getfail(fail[p],i)][s[i]]; ch[p][s[i]]=q; } ++cnt[last=ch[p][s[i]]]; } for(int i=tot;i;--i) cnt[fail[i]]+=cnt[i],ans = max(ans,1ll*cnt[i]*len[i]); }
标签:int,manacher,len,mx,fail,自动机,id,回文 来源: https://www.cnblogs.com/linglinga/p/12218556.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。