【洛谷】P4555 [国家集训队]最长双回文串

P4555 [国家集训队]最长双回文串

题源:https://www.luogu.com.cn/problem/P4555

原理:Manacher

还真比KMP好理解

解决最长回文串问题

转化为长度为奇数的回文串

原串长度 = 新串长度半径 - 1

1. 转化:首位加不同字符,中间加 #

(图片源自AcWing)
2. 求p[i]:以 \(s_i\) 为中心的最大回文串的半径(含中心)

3. 最大半径 - 1 即为所求

注意要用char数组,因为string是动态扩容的,很有可能访问到非法边界
板子:

void init (){
    int k = 0;
    b[k ++] = '$', b[k ++] = '#';
    for (int i = 0; i < a.size(); i ++)
        b[k ++] = a[i], b[k ++] = '#';
    b[k ++] = '^';
    n = k;
}//心里要有张图,构造的时候可不能错

void manacher (){
    init();
    int mr = 0, mid;
    for (int i = 1; i < n; i ++){
        if (i < mr)
            p[i] = min (mr - i, p[2 * mid - i]);
        else
            p[i] = 1;//超过边界就不是回文了
        while (b[i + p[i]] == b[i - p[i]])
            p[i] ++;
        if (i + p[i] > mr)
            mr = i + p[i], mid = i;//找到更大的串了,更新边界

        ans = max (ans, p[i] - 1);

    }
}

思路

一会儿再肝~

posted @ 2022-03-20 18:13  Sakana~  阅读(56)  评论(0编辑  收藏  举报