雙倍回文 Shoi2011 bzoj2342

2022-05-11 03:18:24 字數 1736 閱讀 7729

time limit: 10 sec  memory limit: 128 mb

submit: 2820  solved: 1088

[submit][status][discuss]

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

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

ggabaabaabaaball

12n<=500000

題意就是要求乙個回文串,這個回文串的一半也是回文串,那麼,可以看出這個串的長度必須是4的倍數。。。。。真心想不出,想了30分鐘,並沒有做出來,對回文自動機的理解還不是很充分,看了題解,大部分用了馬拉車,思維題,但也有充分利用回文自動機的性質;觀察回文自動機上的fail鏈,也就是字尾鏈,它滿足fail鏈連向的節點是這個節點最長的回文字尾,那麼,當整個串都新增進去時,fail鏈也就成了fail樹,連線了所有本質不同的回文串,而且,這個是乙個有向的,由小的串往兩邊新增字元成大的串,所以就可以從根節點0號節點開始dfs,記錄乙個桶,表示長度為i的節點在以前出現過,就只要判斷這個串的長度%4==0,並且長度為len/2的節點在以前出現過,這樣就很好的解決了這個問題;

主要是利用了fail鏈與fail樹的性質,求出雙倍回文!!

1 #include2 #include3 #include4 #include5 #include6 #include7 #include"

set"

8 #include"

queue

"9 #include"

vector

"10 #include"

iomanip

"11 #include"

cstring"12

#define inf 1<<29

13#define ll long long

14#define re register

15#define il inline

16#define rep(i,a,b) for(register int i=a;i<=b;++i)

17#define file(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);

18using

namespace

std;

19const

int n=26,maxn=500010;20

struct

edgee[maxn];

23int

ans;

24int

head[maxn],num_e;

25 il void link(int x,int

y) 28

struct

palindromic_tree

37 il void

init()

44 il int get_fail(int

x)48 il void add(int

c) 58 lst=nxt[cur][c];59}

60int

t[maxn];

61 il void dfs(int

x) 68

}pam;

69char

ch[maxn];

70 inline int

gi()

77int

main()

SHOI2011 雙倍回文

輸入分為兩行,第一行為乙個整數,表示字串的長度,第二行有個連續的小寫的英文本元,表示字串的內容。輸出檔案只有一行,即 輸入資料中字串的最長雙倍回文子串的長度,如果雙倍回文子串不存在,則輸出0。16 ggabaabaabaaball 12n 500000 首先manacher求出len陣列 我們發現乙...

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