[模板] manacher算法
时间:2020-07-31 14:09:26
收藏:0
阅读:94
-
在字符串的头部插入‘$‘,在每个字符之间插入‘#‘.
-
用p数组记录以某点为中心的最长回文半径,会发现,最长回文子串长度\(maxlenth=p[i]-1\).
-
那么如何去求p数组呢?我们遍历每个字符,记录回文串能延伸到的最右端的位置\(mx\),之后我们再去判断.
-
(1) mx>i: 1:i的右边界小于mx,那么因为在mx的范围内都是回文串,所以当前的p[i]一定等于对称位置的p[j] (之前已经找过了).
?
? 2:i的右边界大于mx,那么我们可以现将p[i]取为\(mx-i\),然后再去判断\(mx\)的右边是否为回文即可.
?
(2)i超出\(mx\)的边界,那我们只能去暴力判断\(mx\)的右边了
-
记得更新\(mx\),然后维护\(p[i]-1\)的最大值即可得到最长回文串的长度.
-
代码:
char s[N]; char str[N]; int id,mx; int p[N]; int j; void init(){ id=0;mx=0; me(str,0,sizeof(str)); me(p,0,sizeof(p)); int len=strlen(s); str[0]=‘$‘; str[1]=‘#‘; j=2; for(int i=0;i<len;++i){ str[j++]=s[i]; str[j++]=‘#‘; } } void manacher(){ for(int i=0;i<j;++i){ if(i<mx) p[i]=min(mx-i,p[2*id-i]); else p[i]=1; for(;str[i+p[i]]==str[i-p[i]];p[i]++) if(i+p[i]>mx){ mx=i+p[i]; id=i; } } } int main() { //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); scanf("%s",s); init(); manacher(); int ans=0; for(int i=0;i<j;++i){ ans=max(ans,p[i]); } printf("%d\n",ans-1); return 0; }
评论(0)