标签:image lse scanf ++i print turn str als ++
在字符串的头部插入‘$‘,在每个字符之间插入‘#‘.
用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;
}
标签:image lse scanf ++i print turn str als ++
原文地址:https://www.cnblogs.com/lr599909928/p/13409310.html