1. 程式人生 > 其它 >【洛谷】P4555 [國家集訓隊]最長雙迴文串

【洛谷】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);

    }
}

思路

一會兒再肝~