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

 

posted @ 2019-11-09 15:24  双子最可爱啦  阅读(206)  评论(0编辑  收藏  举报