manacher图文
大佬画的,昨天晚上看的大概懂了,今天实现一下。
如果一个字符串正着读和倒着读是一样的,则称它是回文的。
给定一个长度为 N 的字符串 S,求他的最长回文子串的长度是多少。
输入格式
输入将包含最多 30 个测试用例,每个测试用例占一行,以最多 1000000 个小写字符的形式给出。
输入以一个以字符串 END 开头的行表示输入终止。
输出格式
对于输入中的每个测试用例,输出测试用例编号和最大回文子串的长度(参考样例格式)。
每个输出占一行。
输入样例:
abcbabcbabcba
abacacbaaaab
END
输出样例:
Case 1: 13
Case 2: 6
首先是字符串hash +二分 O(nlogn)
#includeusing namespace std; typedef long long ll; typedef unsigned long long ull; const int x = 131; const ull N = 1e6 + 10; ull hr[2 * N], hl[2 * N], p[2 * N] = {1, 0}; char s[2 * N]; ull get(ull h[], int l, int r) { return h[r] - h[l - 1] * p[r - l + 1]; } int main() { int ma = 0, t = 0; while (scanf("%s", s + 1), strcmp(s + 1, "END")) { ma = 0, t++; int n = strlen(s + 1); for (int i = 2 * n; i >= 1; i -= 2) { s[i] = s[i / 2]; s[i - 1] = 'z' + 1; } n *= 2; s[n + 1] = 'z' + 1; n += 1; //puts(s+1); hl[0] = hr[0] = 0; for (int i = 1, j = n; i <= n; i++, j--) { //cout<<0<<' '< > 1; if (get(hl, i - mid, i - 1) == get(hr, n - (i + mid ) + 1, n - (i + 1) + 1)) { l = mid ; } else { r = mid - 1; } //cout << i << ' ' << mid << ' ' << get(hl, i - mid, i - 1) << ' ' << get(hr, n - (i + mid ) + 1, l - i) << endl; } if (s[i - l] == 'z' + 1)ma = max(ma, l ); else ma = max(ma, l + 1); } printf("Case %d: %dn", t, ma); } return 0; }
思路:
Manacher O(n)
#includeusing namespace std; typedef long long ll; typedef unsigned long long ull; const int x = 131; const ull N = 1e6 + 10; int p[2 * N], mid, ma = -1; char s[N], str[2 * N]; int res = 0, d_re, cnt=0; void init() { cnt = 0; int l = strlen(s + 1); str[cnt++] = '@'; for (int i = 1; i <= l; i++) { str[cnt++] = '#', str[cnt++] = s[i]; } str[cnt++] = '#'; str[cnt] = '%'; } int manacher() { int l=cnt; res=0,mid=0,ma=0; for (int i = 1; i <= l; i++) { //cout< = i) {//网上大多是 > p[i] = min(ma - i, p[2 * mid - i]); } else p[i] = 1; while (str[i + p[i]] == str[i - p[i]])p[i]++; if (i + p[i]-1 > ma) { //大多是 i+p[i]>ma ma = i + p[i]; mid = i; res=max(res,p[i]); // cout << i << ' ' << mid << ' ' << ma << endl; } } return (res-1); } int main() { int t = 0; while (scanf("%s", s + 1), strcmp(s + 1, "END")) { t++; init(); //puts(str); printf("Case %d: %dn", t, manacher()); } return 0; }
在实现代码的时候,我一直在想昨晚上更行ma的情况,所以改了一下没想到成了。。。。。



