[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。首先由題意可知,只用考慮偶數長的回文串。這樣就不用插入 直...