2565: 最长双回文串
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2730 Solved: 1377
[Submit][Status][Discuss]
Description
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。
Input
一行由小写英文字母组成的字符串S。
Output
Sample Input
Sample Output
HINT
样例说明
从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。
对于100%的数据,2≤|S|≤10^5
2015.4.25新加数据一组
Source
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; char s[300010], ss[300010]; int ans, len, r[300010], f1[300010], f2[300010], n; void init() { int p = 1, mx = 1; for (int i = 1; i <= n; i++) { int x = 0; if (i < mx) x = min(r[p * 2 - i], mx - i); else x = 1; while (ss[i + x] == ss[i - x]) x++; r[i] = x; if (i + x > mx) { mx = i + x; p = i; } } } int main() { scanf("%s", s + 1); len = strlen(s + 1); s[0] = '('; for (int i = 1; i <= len; i++) ss[++n] = '#', ss[++n] = s[i]; ss[++n] = '#'; ss[n + 1] = ')'; init(); int mx = 1; for (int i = 1; i <= n; i++) if (i + r[i] > mx) { for (int j = mx + 1; j <= i + r[i]; j++) f1[j] = j - i + 1; mx = i + r[i] - 1; } mx = n; for (int i = n; i >= 1; i--) if (i - r[i] < mx) { for (int j = mx - 1; j >= i - r[i]; j--) f2[j] = i - j + 1; mx = i - r[i] + 1; } for (int i = 1; i <= n - 3; i++) if (ss[i] != '#') ans = max(ans, f1[i] + f2[i + 2]); printf("%d\n", ans); return 0; }