P1723 高手过愚人节
题目背景
高手组织大家过愚人节、联欢会要打出一些横幅。高手想表现得文艺一点,于是他就用一些普通人看不懂的乱码作为横幅内容。但是在这个时候,他也想让横幅更美观。
题目描述
现在给出N个著名的乱七八糟的乱码,高手要知道每条乱码的最美观连续子序列的长度,在高手的心目中,只有回文串才是美观的。这代表着他纯洁的爱情,又有着回环往复的美,最重要的是,对于转回了一年级的高手来说,想要求出这个太难了,因此他找到了你。(OIer无所不能!)
输入格式
第一行,n。
接下来n行 每行一条乱码。
输出格式
n行,每行为对应乱码的最美观连续子序列的长度,即最长连续回文子串长(但是由于高手听不懂,我们不会这样说)。
输入输出样例
输入 #1
1 aaaaa
输出 #1
5
说明/提示
zxy大神提供、本人改编上传。
思路
求最长连续回文子串长,DP必超时(50分),用Manacher
代码
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=21000000; int k[N],n; char s[N],ss[N]; int init() { int len=strlen(s); ss[0]='@',ss[1]='#'; int j=1; for(int i=0; i<len; ++i) { ss[++j]=s[i]; ss[++j]='#'; } ss[++j]='\0'; return j; } int solve() { int id=1,mx=1,M=0,len=init(); for(int i=1; i<len; ++i) { if(i<mx) k[i]=min(k[id*2-i],mx-i); else k[i]=1; while(ss[i-k[i]]==ss[i+k[i]]) k[i]++; if(i+k[i]>mx) { mx=i+k[i]; id=i; } M=max(M,k[i]-1); } return M; } int main() { scanf("%d",&n); while(n--) { memset(k,0,sizeof(k)); cin>>s; printf("%d\n",solve()); } return 0; }