对给定的字符串,本题要求你输出最长对称子串的长度。例如,给定"Is PAT&TAP symmetric?",最长对称子串为"s PAT&TAP s",于是你应该输出11。
输入格式:
输入在一行中给出长度不超过1000的非空字符串。
输出格式:
在一行中输出最长对称子串的长度。
输入样例:Is PAT&TAP symmetric?输出样例:
11
emmm看着数据量n^2的应该能过的吧,虽然我是用Manacher的。不知道只是什么的读者可以百度一下,是一种十分优秀的求最长回文子串的算法(时间复杂度O(N))。
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
using namespace std;
const int maxn = int(1e4) + 100;
const int inf = 0x7fffffff;
typedef long long LL;
typedef unsigned long long ull;
char s[maxn];
struct Manacher {
char s2[maxn];//修正串,即插入字符
int len2;//修正后的长度
int cnt[maxn];
int ans;//结果
int solve(char *s1, int len1) {//原串和原串的长度
len2 = 0;
s2[len2++] = '$', s2[len2++] = '#';//插入的符号只要不是原串总有的就行,通常为#
for (int i = 0; i < len1; i++) {
s2[len2++] = s1[i];
s2[len2++] = '#';//使原串变为奇数串
}
s2[len2++] = '\0';
memset(cnt, 0, sizeof(cnt));
for (int i = 1, j = 0; i < len2; i++) {
if (cnt[j] + j>i)
cnt[i] = min(cnt[2 * j - i], cnt[j] - (i - j));
else
cnt[i] = 1;
for (cnt[i]; s2[i - cnt[i]] == s2[i + cnt[i]]; cnt[i]++);
if (i + cnt[i]>j + cnt[j])
j = i;
}
ans = 0;
for (int i = 0; i<len2; i++)
if (ans<cnt[i])
ans = cnt[i];
return ans - 1;
}
}man;
int main() {
gets(s);
printf("%d\n", man.solve(s, strlen(s)));
}