manachar算法用来处理字符串的最长回文子串的算法,其核心就是预处理len数组.
假设原串是s[0...n-1],len[i]表示以s[i]为回文中心的最长回文串的右下标到i的长度,
然后递推瞎搞.
因为算法本身比较简单网上烂大街,主要还是想了一下复杂度.
容易发现Max指针最多扩展到n,而复杂度主要在于while循环,每次都会增加Max指
针或者跳出while循环,所以复杂度最多就是O(n+chang(Max))=O(n).
HDU 3068:点击打开链接
模板题
#include <bits/stdc++.h>
using namespace std;
#define maxn 111111
int len[maxn<<1];
char a[maxn];
int manachar (char *p) {
char s[maxn<<1];//构造新串
int n = strlen (p), l = 0;
s[l++] = '@';
s[l++] = '#';
for (int i = 0; i < n; i++) {
s[l++] = p[i];
s[l++] = '#';
}
s[l++] = '~'; s[l] = 0;
//cout << s << endl;
int Max = 0, pos = 0, ans = 0;
for (int i = 1; i < l; i++) {
if (Max > i) {
len[i] = min (len[2*pos-i], Max-i);
}
else
len[i] = 1;
while (s[i+len[i]] == s[i-len[i]])
len[i]++;
ans = max (ans, len[i]);
if (len[i]+i > Max) {
Max = len[i]+i;
pos = i;
}
}
return ans-1;
}
int main () {
while (scanf ("%s", a) == 1) printf ("%d\n", manachar (a));
return 0;
}
POJ 3974:点击打开链接
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 2211111
int len[maxn];
char s[maxn];
char a[maxn];
int Manachar (char *p) {
int n = strlen (p), l = 0;
s[l++] = '@';
s[l++] = '#';
for (int i = 0; i < n; i++) {
s[l++] = p[i];
s[l++] = '#';
}
s[l] = 0;
int Max = 0, pos = 0, ans = 0;
for (int i = 1; i < l; i++) {
if (Max > i) {
len[i] = min (len[2*pos-i], Max-i);
}
else
len[i] = 1;
while (s[i+len[i]] == s[i-len[i]])
len[i]++;
ans = max (ans, len[i]);
if (len[i]+i > Max) {
Max = len[i]+i;
pos = i;
}
}
return ans-1;
}
int main () {
int kase = 0;
while (scanf ("%s", a) == 1) {
if (a[0] == 'E')
break;
printf ("Case %d: %d\n", ++kase, Manachar (a));
}
return 0;
}