bzoj 2342 Shoi2011 雙倍回文

2021-06-26 13:24:51 字數 1418 閱讀 4672

題目大意:

演算法一:

因為雙倍回文串必定是乙個回文串

所以先用manachar求出每個點能夠擴充套件出的最長的回文串長度f[i]

再列舉對稱軸x,

對於y只要滿足y-f[y]<=x && y<=x+f[x]/2,就可以用len(x,y)*4來更新答案

對於每個x,只需要用距離其最遠的滿足條件的y來更新即可

將其按i-f[i]進行排序,在到x時,把所有i-f[i]<=x的i插入到乙個樹狀陣列中

然後就是查詢小於某個值得最大值是多少,這個二分一下就好了,運用樹狀陣列的獨特優越性,可以省掉乙個log2(n),總複雜度o(nlog2(n))

具體做法看**

#include#include#include#include#includeusing namespace std;

const int maxn=500011;

int quit,n;char s[maxn];

void init()

struct tbit

int find(int x,int ans=0)

int query(int r)

for (int i=1;i<=n;++i) l[i]=i-f[i];

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

sort(p+1,p+n+1,cmp);int ans=0;

for (int i=1,now=1;i<=n;++i)

ans*=4;printf("%d\n",ans);

}int main()

演算法二:

還是用manacher先求出f[i]

然後列舉對稱軸x,我們發現對於y,滿足x-f[x]/2<=y<=x 且y+f[y]>=x就可以用len(x,y)*4來更新

我們發現對於每個y它如果不能與t更新,就一定不能與t+1更新,所以我們可以每次把不能用來更新的點刪掉

具體地說,就是找x-f[x]/2後第乙個沒有被刪掉的點來與x更新答案,這個可以用並查集來維護,如果把乙個點刪掉,就把它連到它後乙個點

複雜度o(kn) k是並查集常數

#include#includeusing namespace std;

const int maxn=500011;

int quit,n,fa[maxn];char s[maxn];

void init()

int find(int x)

void work()

for (int i=1;i<=n;++i) fa[i]=i;int ans=0,now;

for (int i=1;i<=n;ans=max(ans,i++-now))

for (now=find(i-f[i]/2);now+f[now]

雙倍回文 Shoi2011 bzoj2342

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

SHOI2011 bzoj2342 雙倍回文

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

bzoj2342 Shoi2011 雙倍回文

傳送門 參考題解 一道很好的manacher練手題。一開始把題讀錯了,以為是w1 w 1w 2w 2 形式的就可以,題目哪有這麼簡單 觀察題目,我們可以發現 對於每乙個符合條件的子串,都有j p j i j i,p j 是以j為中心最大的 畫個圖可能更好理解 圖中綠色矩形中就是一種可行方案。所以ma...