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;
}

浙公网安备 33010602011771号