解题思路
(1)我们可以用二分+哈希来做,首先从前后两端分别哈希一次,然后枚举回文串的中心(对称点),二分对称字符串长度,根据哈希直接判断中心点两端字符串是否相同,然后就没了。。
(2)马拉车。。(不是我打这题的重点,解释起来也比较麻烦,就,略过吧。。代码放了,饶了我吧)
PS:长度要分成奇偶两种分别做,奇数时字符串长度为2mid+1,偶数时为2mid。
代码
马拉车 <——写的超棒
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int ans,q,x,y,l,k,cnt,len[3000010];
char s[3000010],c[3000010];
void yu()
{
s[k]='@';
for(int i=1; i<=l; i++)
{
s[++k]='#';
s[++k]=c[i];
}
s[++k]='#';
s[++k]='%';
}
int malacher()
{
int mx=0,sum=0,id=0;
for(int i=1; i<k; i++)
{
if(i<mx)len[i]=min(mx-i,len[id-(i-id)]);
else len[i]=1;
while(s[i-len[i]]==s[i+len[i]])len[i]++;
if(len[i]+i>mx)
{
mx=len[i]+i;
id=i;
sum=max(sum,len[i]);
}
}
return (sum-1);
}
int main()
{
scanf("%s",c+1);
while(!(c[1]=='E'&&c[2]=='N'&&c[3]=='D'))
{
cnt++;
l=strlen(c+1);
k=0;
memset(len,0,sizeof(len));
yu();
ans=malacher();
printf("Case %d: %d\n",cnt,ans);
scanf("%s",c+1);
}
}
二分+哈希
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iomanip>
#include <cmath>
using namespace std;
typedef unsigned long long ull;
ull p=131;
ull a[1000010],base[1000010],b[1000010];
int n,ans,cnt;
string s;
bool check()
{
if(s[0]=='E'&&s[1]=='N'&&s[2]=='D')
return 1;
return 0;
}
void hash()
{
memset(base,0,sizeof(base));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
base[0]=1ull;
for(int i=0; i<n; i++) {
base[i+1]=base[i]*p;
a[i+1]=a[i]*p+(s[i]-'a');//正序字符串哈希
}
for(int i=n-1; i>=0; i--)
b[i+1]=b[i+2]*p+(s[i]-'a');//倒序字符串哈希
}
void work()
{
for(int i=1; i<=n; i++) {//找中心
int mid=0,l=0,r=n;
while(l<=r) {//长度奇数
mid=(l+r)>>1;
if(i-mid<1||i+mid>n)
{
r=mid-1;
continue;
}
if(a[i]-a[i-mid-1]*base[mid+1]==b[i]-b[i+mid+1]*base[mid+1])
{
ans=max(ans,mid*2+1);
l=mid+1;
}
else r=mid-1;
}
mid=0,l=0,r=n;
while(l<=r) {//长度偶数
mid=(l+r)>>1;
if(i-mid+1<1||i+mid>n)
{
r=mid-1;
continue;
}
if(a[i]-a[i-mid]*base[mid]==b[i+1]-b[i+mid+1]*base[mid])
{
ans=max(ans,mid*2);
l=mid+1;
}
else r=mid-1;
}
}
}
int main()
{
cin>>s;
n=s.size();
while(!check()) {
cnt++;
ans=1;
hash();
work();
printf("Case %d: %d\n",cnt,ans);
cin>>s;
n=s.size();
}
}