您的位置:首页 > 其它

UVALive - 4975_Casting Spells

2013-10-18 19:12 232 查看
题意很简单,给你一个字符串,要求你求出一个最长的形似于w(wr)w(wr)的最长连续子串的长度。wr表示w的逆序串。

在这里大家很容易就能想到Manacher算法求回文串。没有错,就是这个。

算法的详细过程我就不说了,直接说后面的实现吧。

通过manacher算法我们可以在O(N)的时间复杂度以内求出一每两个字符空缺处为对称轴的最长回文串的长度。

这样我们可以对于每一个空缺位置逐一枚举,然后分别对匹配求出一个最长的回文串就可以了。

中间有好多细节要优化哦,我wa了好几发。还有在写的时候一定要写出各种优化。代码不要写挫了。

#include <iostream>
#include <cstring>
#include <cstdio>
#define maxn 1000100
using namespace std;

char tep[maxn],s[2*maxn];
int a[2*maxn],n,ans,now;

void init()
{
now=2;
s[0]='@';
s[1]='#';
for (int i=0; tep[i]; i++)
{
s[now++]=tep[i];
s[now++]='#';
}
s[now]='$';
s[now+1]=0;
}

void deal()
{
memset(a,0,sizeof a);
int mx_c=0,mx_r=0;
a[0]=1;
for (int i=1; i<now; i++)
{
if (mx_r>i)
{
a[i]=min(mx_r-i+1,a[2*mx_c-i]);
}
else a[i]=1;
while (s[i-a[i]]==s[i+a[i]]) a[i]++;
if (i+a[i]>mx_r) mx_r=i+a[i]-1,mx_c=i;
}
}

int main()
{
int cas;
scanf("%d",&cas);
while (cas--)
{
scanf("%s",tep);
for (int i=0; tep[i]; i++)
if (tep[i]>='A' && tep[i]<='Z')
tep[i]=tep[i]-'A'+'a';
ans=0;
init();
deal();
for (int i=1; s[i]; i+=2)//这里一定是+2,只有空缺处才是满足条件的。
{
int cur=a[i]-1;
while (cur%4!=0 || cur/2>=i) cur--;
for (; cur>ans; cur-=4)
{
if (a[i+cur/2]>=cur/2+1 && a[i-cur/2]>=cur/2+1)
{
ans=cur;
break;
}
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: