BZOJ2342 Shoi2011 雙倍回文

2022-05-09 17:08:03 字數 1886 閱讀 3714

[bzoj2342][shoi2011]雙倍回文

試題描述

輸入

輸入分為兩行,第一行為乙個整數 n,表示字串的長度,第二行有 n 個連續的小寫的英文本元,表示字串的內容。

輸出

輸出檔案只有一行,即:輸入資料中字串的最長雙倍回文子串的長度,如果雙倍回文子串不存在,則輸出0

輸入示例

16

ggabaabaabaaball

輸出示例

12
資料規模及約定

n<=500000

題解

對於乙個形如 wrwwrw 的串,我們不妨考慮它的四分之一。

先用 manacher 求出 p[i] 陣列,對於乙個子串 str(l, r)(原串從位置 l 到位置 r 的連續部分)滿足能成為乙個雙回文串的四分之一當且僅當 l + p[l] - 1 ≤ r 且 r - p[r] / 2 + 1 ≤ l,於是我們可以把每個位置 r 按照 r + p[r] - 1 從大到小排序,然後平衡樹(或 set)維護一下當前所有大於等於 r + p[r] - 1 的位置,然後找到大於等於 r - p[r] / 2 + 1 的最小數就是最優的 l,那麼就可以用 r - l + 1 更新答案啦。

#include #include #include #include #include #include #include #include #include #include #include using namespace std;

int read()

while(isdigit(c))

return x * f;}

#define maxn 1000010

#define oo 2147483647

struct node

node(int _, int __): v(_), r(__) {}

} ns[maxn];

int rt, tot, fa[maxn], ch[maxn][2];

void rotate(int u)

void insert(int& o, int v)

bool d = v > ns[o].v;

insert(ch[o][d], v); fa[ch[o][d]] = o;

if(ns[ch[o][d]].r > ns[o].r)

return ;

}int qupp(int o, int v)

char str[maxn], s[maxn];

int n, len[maxn], alp[maxn], pos[maxn];

bool cmp(int a, int b)

int main()

// for(int i = 1; i <= n; i++) printf("%d%c", len[i], i < n ? ' ' : '\n');

for(int i = 1; i <= n; i++) pos[i] = i;

sort(pos + 1, pos + n + 1, cmp);

int ans = 0;

for(int i = n, j = 1; i; i--)

if(s[i] != '#') continue;

int t = qupp(rt, i - (len[i] + 1 >> 1) + 1);

ans = max(ans, alp[i] - alp[t-1] << 2);

}printf("%d\n", ans);

return 0;

}

雙倍回文 Shoi2011 bzoj2342

time limit 10 sec memory limit 128 mb submit 2820 solved 1088 submit status discuss 輸入分為兩行,第一行為乙個整數,表示字串的長度,第二行有個連續的小寫的英文本元,表示字串的內容。輸出檔案只有一行,即 輸入資料中字串...

bzoj 2342 Shoi2011 雙倍回文

題目大意 演算法一 因為雙倍回文串必定是乙個回文串 所以先用manachar求出每個點能夠擴充套件出的最長的回文串長度f i 再列舉對稱軸x,對於y只要滿足y f y x y x f x 2,就可以用len x,y 4來更新答案 對於每個x,只需要用距離其最遠的滿足條件的y來更新即可 將其按i f ...

SHOI2011 bzoj2342 雙倍回文

description input 輸入分為兩行,第一行為乙個整數,表示字串的長度,第二行有個連續的小寫的英文本元,表示字串的內容。output 輸出檔案只有一行,即 輸入資料中字串的最長雙倍回文子串的長度,如果雙倍回文子串不存在,則輸出0。首先由題意可知,只用考慮偶數長的回文串。這樣就不用插入 直...