Manacher 算法

学习视频
\(O(n)\) 求最长回文字符串
1.将原字符串转化

  • 记得\(ms,mp\)的长度要开到原数组的两倍
  • \(s\)数组为字符串,\(ms\)为转化后的字符串
  • \(0\)位置插入边界\(\$\),在结尾位置插入\(0\)
  • 其他情况,每个原字符串中的字母都用两个\(\#\)来包围
int l = 0;
ms[l ++] = '$';
ms[l ++] = '#';
for(int i = 0;i < len; ++i) {
    ms[l ++] = s[i];
    ms[l ++] = '#';
}
ms[l] = 0;

2.求最长回文半径

  • 这个回文半径是对于\(mp\)数组而言的,对于原数组\(str\)\(mp[i] - 1\),就是原数组的回文长度
  • \(mx\) 代表以\(id\) 为中心的回文串长度的右边界
  • \(mp\) 数组代表了以\(i\) 为中心的回文串半径
  • 因为以\(id\) 为中心的回文串在$ i< id+mp[id] $ 的情况下,
    • 一定可以找到\(mx-i,2\times id - i\)这两个串,他们都在\(id\)的回文半径内
    • \(i + j = 2\times id\),所以\(j = 2\times id - i\)
  • 当更新了\(mp[i]\)之后,尝试扩展\(mp[i]\)的半径,\(while\)循环即可
  • 最后更新当前的\(id,mx\)
int mx = 0,id = 0;
for(int i = 0;i < l; ++i) {
    mp[i] = mx > i ? min(mp[2 * id - i],mx - i) : 1;
    while(ms[i + mp[i]] == ms[i - mp[i]]) mp[i] ++;
    if(i + mp[i] > mx) {
        mx = i + mp[i];
        id = i;
    }
}

模板题

POJ 3974

#include <iostream>
#include <cstring>
using namespace std;
#define endl '\n' 
#define IO ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define lowbit(x) ((x)&(-x))
typedef long long ll;
typedef double db;
typedef pair<int,int> PII;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const db EXP = 1e-9;
char ms[N << 1],str[N];
int mp[N << 1];
void manacher(char s[],int len) {
    int l = 0;
    ms[l ++] = '$';
    ms[l ++] = '#';
    for(int i = 0;i < len; ++i) {
        ms[l ++] = s[i];
        ms[l ++] = '#';
    }
    ms[l] = 0;
    int mx = 0,id = 0;
    for(int i = 0;i < l; ++i) {
        mp[i] = mx > i ? min(mp[2 * id - i],mx - i) : 1;
        while(ms[i + mp[i]] == ms[i - mp[i]]) mp[i] ++;
        if(i + mp[i] > mx) {
            mx = i + mp[i];
            id = i;
        }
    }
}
int main() {
    IO;
    int cnt = 1;
    while(cin >> str) {
        if(strcmp(str,"END") == 0) break;
        cout << "Case " << cnt ++ << ": ";
        int len = strlen(str),ans = 0;
        manacher(str,len);
        for(int i = 1;i <= len * 2; ++i) ans = max(ans,mp[i]);
        cout << ans - 1 << endl;
    }
    return 0;
}
posted @ 2020-03-30 17:40  南风--  阅读(86)  评论(0编辑  收藏  举报