manacher算法 (模板)

介绍

计算字符串每个位置的最长回文串,也可以说是计算所有的回文区间。

原理

感觉算法思想和扩展kmp求extend数组十分类似。

先在第一个位置插入'$'以避免小于0的讨论,再在每一个字符之间都插入'#',为了避免对区间奇偶长度的讨论。

用len[i]代表位置i的最长回文右半区间的长度。由于经过上面的处理,这里右半区间的长度就是原字符串的回文区间总长。

设p代表计算过程中,到达的最右边界。a代表对应p的位置。i对a对称的位置为2 * a - i。如果i + len[2 * a - i]没有超过p的范围那么len[i] = len[2 * a - i]。否则就延长并更新p和a。

这里 len[i]-1 就是以位置i中心的回文总长。这里的i包括间隙的位置,从1开始编号。

string s;
char ss[N]; //ss为原串
int len[2 * N]; //结果
void mana() {
    s.clear();
    s.push_back('$');
    s.push_back('#');
    for(int i = 0; ss[i]; i++) {
        s.push_back(ss[i]);
        s.push_back('#');
    }

    int a = 1, p = 1;
    for(int i = 1; i < s.size(); i++) {
        if(i < p && len[2 * a - i] < p - i) len[i] = len[2 * a - i];
        else {
            int l = p - i;
            while(i + l < s.size() && s[i + l] == s[i - l]) l++;
            len[i] = l;
            a = i;
            p = i + l;
        }
    }
}

posted @ 2020-04-13 23:44  limil  阅读(183)  评论(0编辑  收藏  举报