Manacher算法
算法过程分析
- 参考资料 https://subetter.com/algorithm/manacher-algorithm.html
- 由于回文分为偶回文(比如 bccb)和奇回文(比如 bcacb),而在处理奇偶问题上会比较繁琐,所以这里我们使用一个技巧,具体做法是:在字符串首尾,及各字符间各插入一个字符(前提这个字符未出现在串里)。举个例子:s=“abbahopxpo”,转换为s_new="$#a#b#b#a#h#o#p#x#p#o#"。
- 定义一个辅助数组int p[],其中p[i]表示以 i 为中心的最长回文的半径
- j回文串有一部分在id回文串外
- p[i] = mx - i;
- j回文串均在id回文串内
- p[i] = p[2*id - 1];
- j回文串左端与id回文串左端重合
- p[i] = p[2*id - 1] / mx - i;
-
while (s_new[i - p[i]] == s_new[i + p[i]]) p[i]++;
例题
- POJ 3974
- 模版题
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef unsigned long long ULL; const int MAXN = 1000001; int n, ans = 1, cnt = 0, p[2 * MAXN]; char s[MAXN], new_s[2 * MAXN]; int getInit() { int len = strlen(s); int cur = 2; new_s[0] = '$'; new_s[1] = '#'; for (int i = 0; i < len; i++) { new_s[cur++] = s[i]; new_s[cur++] = '#'; } new_s[cur] = '\0'; return cur; } int Manacher() { int mx = 0, id; int len = getInit(); for (int i = 0; i < len; i++) { if (i < mx) p[i] = min(p[2 * id - i], mx - i); else p[i] = 1; while (new_s[i - p[i]] == new_s[i + p[i]]) p[i]++; if (mx < i + p[i]) { id = i; mx = i + p[i]; } ans = max(ans, p[i] - 1); } return ans; }
- 模版题
- HDU 4513
- Manacher + 单调性预处理
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef unsigned long long ULL; const int MAXN = 1000001; int n, ans = 1, cnt = 0, p[2 * MAXN], t, a[MAXN], h[MAXN]; int new_a[2 * MAXN]; int getInit() { int cur = 1; new_a[0] = -2; for (int i = 1; i <= n; i++) { new_a[cur++] = a[i]; new_a[cur++] = -2; } return cur; } void Manacher() { int mx = 0, id; int len = getInit(); for (int i = 0; i <= len; i++) { if (i < mx) p[i] = min(p[2 * id - i], mx - i); else p[i] = 1; while (new_a[i - p[i]] == new_a[i + p[i]]) p[i]++; if (mx < i + p[i]) { id = i; mx = i + p[i]; } } } int main() { scanf("%d", &t); while (t--) { ans = 0; memset(h, 0, sizeof(h)); scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); if (a[i - 1] <= a[i]) h[i] = h[i - 1] + 1; else h[i] = 1; } Manacher(); for (int i = 0; i <= 2 * n; i++) { if (new_a[i] != -2) ans = max(min(h[i / 2] * 2 + 1, p[i] - 1), ans); else ans = max(min(h[i / 2] * 2, p[i] - 1), ans); } printf("%d\n", ans); } return 0; } ···
- Manacher + 单调性预处理