Palindrome Page69 哈希+二分
最大回文串还可以用马拉车算法求解,时间更优一些
分析:对于一个回文串,一共会有两种情况:
- 长度为奇数,
- 长度为偶数,
对于每一个位置 ,分这两种情况,二分得出以这个位置为“中心”可以最大延伸的位置。
分析二分合理性:假设中心为 的最大奇回文串长度为 ,则对于任意的 ,中心为 ,长度为 的子串一定为回文串。但是对于 ,中心为 ,长度为 的子串显然不是回文串。
时间复杂度:
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<queue>
#include<map>
#define ll long long
#define ull unsigned long long
#define pb push_back
#define rep(x,a,b) for (int x=a;x<=b;x++)
#define repp(x,a,b) for (int x=a;x<b;x++)
#define W(x) printf("%d\n",x)
#define WW(x) printf("%lld\n",x)
#define pi 3.14159265358979323846
#define mem(a,x) memset(a,x,sizeof a)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int maxn=2e6+7;
const int INF=1e9;
const ll INFF=1e18;
char s[maxn];
int K=0,l,r,mid;
ull f1[maxn],p[maxn],f2[maxn];
int Hash1(int l,int r)
{
return f1[r]-f1[l-1]*p[r-l+1];
}//正向哈希值
int Hash2(int l,int r)
{
return f2[l]-f2[r+1]*p[r-l+1];
}//逆向哈希值
int main()
{
while(scanf("%s",s+1)&&(strcmp(s+1,"END")!=0))
{
int n=strlen(s+1),ans=1;
p[0]=1,f1[0]=f2[0]=0;
for (int i=1;i<=n;i++)f1[i]=f1[i-1]*131+s[i]-'a'+1,p[i]=p[i-1]*131;
for (int i=n;i>=1;i--)f2[i]=f2[i+1]*131+s[i]-'a'+1;
rep(i,1,n)
{
l=0,r=i-1;
while(l<r)
{
mid=(l+r+1)>>1;
if (Hash1(i-mid,i)==Hash2(i,i+mid))l=mid;
else r=mid-1;
}
ans=max(ans,2*l+1);
l=0,r=i-1;
while(l<r)
{
mid=(l+r+1)>>1;
if (Hash1(i-mid,i-1)==Hash2(i,i+mid-1))l=mid;
else r=mid-1;
}
ans=max(ans,2*l);
}
printf("Case %d: %d\n",++K,ans);
}
return 0;
}