马拉车算法
作用: 可以在O(n)的时间内求出最大的回文子串
各项定义说明:
字符串fa预处理后的字符串
C已经求出离当前位置最近回文字串的对称位置
r关于C对称的回文子串的右端点
镜点是当前点关于c的对称点
性质:对称性
对于该点的最长回文子串只有三种可能,一种是和关于C的镜点完全一样;
第二种是由于镜点的回文子串中存在C的右边界中的点,所以我们只取从最左边到镜点的长度即可
第三种情况是由于当前点的还包含不在该回文子串中的点
详解
对于第一点是关于C对称的回文子串从左边到镜点和从右边到当前点是完全一样的因此,如果镜点所求的回文串完全包含在这个回文串中的话,由于对称性,当前点最小的长度是和镜点完全相等的
对于第二点镜点的回文子串长度比当前长度大,那么它包含的从最左边到镜点也一定会是对称的
第三点可以看作是前两点的延申,我们可以通过对点比较的方法进行延长来求出结果
每次求完之后更新r和c
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e7;
int p[N];
signed main() {
string a;
cin>>a;
string fa="@";
for(auto it:a)fa+="#",fa+=it;
fa+="#!"; int ma=0;
//马拉车算法
int r=0,c=0;
for(int i=1;fa[i];i++)
{
int k=2*c-i;
if(i<r)p[i]=min(p[k],r-i);
while(fa[i+p[i]+1]==fa[i-p[i]-1])p[i]++;
if(i+p[i]>r)
{
r=i+p[i];
c=i;
}
(要求求值) ma=max(ma,p[i]);
}
cout<<ma<<"\n";
}