1. 程式人生 > >P4555 [國家集訓隊]最長雙回文串

P4555 [國家集訓隊]最長雙回文串

con truct inline ++ 一個 國家集訓隊 .cn oid !=

題意:求這樣一個回文串S,S = A + B 且 A, B都是回文串。問最長S

題解:建立兩顆回文樹,一個從前向後插,一個從後向前插,並記錄每個位置得到的最長後綴後文。

ps:馬拉車的做法待更

const int N = 100005;

struct data {
    int len, fail;
    int ch[26];
};

struct PldTree {
    int tot, last;
    int cnt[N];

    char s[N];
    data node[N];

    void Inite() {
        tot = last = 1;
        node[
0].fail = 1; node[1].len = -1; } void Insert(int i) { while(s[i] != s[i - node[last].len - 1]) last = node[last].fail; if (!node[last].ch[s[i] - a]) { node[++tot].len = node[last].len + 2; cnt[i] = node[tot].len; int tp = node[last].fail;
while(s[i] != s[i - node[tp].len - 1]) tp = node[tp].fail; node[tot].fail = node[tp].ch[s[i] - a]; node[last].ch[s[i] - a] = tot; last = tot; } else { last = node[last].ch[s[i] - a]; cnt[i] = node[last].len; } } }; PldTree T1, T2; inline
void upd(int &a, int b) { (a < b) && (a = b); } int main() { T1.Inite(); T2.Inite(); T1.s[0] = T2.s[0] = 0; scanf("%s", T1.s + 1); int n = strlen(T1.s + 1); Rep(i, 1, n) { T2.s[i] = T1.s[n + 1 - i]; T1.Insert(i); } Rep(i, 1, n) { T2.Insert(i); } int ans = 0; Rep(i, 1, n) upd(ans, T1.cnt[i] + T2.cnt[n - i]); pr(ans); return 0; }

P4555 [國家集訓隊]最長雙回文串