P4555 [國家集訓隊]最長雙回文串
阿新 • • 發佈:2018-09-08
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; inlinevoid 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 [國家集訓隊]最長雙回文串