题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5371
题意:
求出三段连续的序列,使得第一段是第二段的回文,第二段是第三段的回文,求出最长序列是多长。
思路:
manacher算法,处理回文串。
枚举 i,满足mp[i] >= j-i+1 && mp[j] >= j-i+1, 更新答案 ans = j-i。
AC.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#pragma comment(linker,"/STACK:1024000000,1024000000")
using namespace std;
const int maxn = 1e5+5;
int s[maxn*2];
int mp[maxn*2];
void manacher(int m)
{
int mx = 0, id = 0;
for(int i = 0; i < m; ++i) {
mp[i] = mx > i? min(mp[2*id-i], mx-i): 1;
while(s[i+mp[i]] == s[i-mp[i]]) mp[i]++;
if(i + mp[i] > mx) {
mx = i + mp[i];
id = i;
}
}
}//最长回文序列的长度只会出现在打标记的地方。
int main()
{
//freopen("in", "r", stdin);
int T, ca = 0;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
int len = 0;
s[len++] = -1;
s[len++] = -10;
for(int i = 1; i <= n; ++i) {
scanf("%d", &s[len++]);
s[len++] = -10;
}
s[len++] = -1;
manacher(len);
int ans = 0;
for(int i = 1; i < len; i+=2) {
printf("%d %d\n", s[i], mp[i]);
for(int j = i+mp[i]-1; j - i > ans; j-=2) {
if(mp[j] >= j-i+1 && ans < j-i) {
ans = j-i;
break;
}
}
}
printf("Case #%d: %d\n", ++ca, ans/2*3);
}
return 0;
}