Manacher 马拉车算法 求最长的回文串

Manacher算法 求最长回文串

len[i] 表示以 i 为中心的最长回文串长度,pos 储存目前右边界最大的回文串中心, mx为右边界。

当 i 小于 mx 时,那么以 i 为中心的回文串有三种可能的情况:

1、len[2 * pos - i] 如果小于 mx,则 len[i] = len[2 * pos - i];

2、len[2 * pos - i] 如果大于 mx,则 len[i] = mx - i;

3、len[2 * pos - i] 如果等于 mx,则 len[i] = len[2 * pos - i],然后再向左右扩展循环判断是否一致,如果一致 len[i]++;

当 i 大于等于 mx 时,就无法通过已知的数据求解 len[i],只能令 len[i] 先等于 1,然后向左右扩展求解

其中为了保证判断的回文串是奇回文串,要在每个元素中间和整个字符串的左右插入一个不常用字符 '#'

#include
#include
#include
using namespace std;

int len[10000];
string manacher(string a){
    string str = "#";
    for(int i=0; i < a.size(); i++)
        str = str + a[i] + '#';
    int str_len = str.size();

    int mx = 0, pos = 0, mlen = 0, ans = 0;
    for(int i=0; i < str_len; i++){
        if(i < mx) len[i] = min(mx - i, len[2*pos - i]);
        else len[i] = 1;
        while(i-len[i] >= 0 && i+len[i] < str_len && str[i-len[i]] == str[i+len[i]]) len[i]++;
        if(len[i]+i > mx){
            mx = len[i] + i;
            pos = i;
            if(mlen < len[i]){
                mlen = len[i];
                ans = i;
            }
        }
    }
    string res = "";
    for(int i=ans-mlen+1; i < ans+mlen; i++)
        if(str[i] != '#') res = res + str[i];
    return res;
}
int main(){
    string str;
    while(cin >> str){  
        cout << manacher(str) << endl;
    }
    return 0;
}

你可能感兴趣的:(Manacher 马拉车算法 求最长的回文串)