P4555 最長雙回文串

2022-02-27 08:42:27 字數 1402 閱讀 4506

\(t=xy\),其中 \(x,y\) 均為回文串,求 \(t\) 的最大長度

首先把每兩個原有字元的間隙填充上其他字元,然後可以用 manacher 求出每個點的最大回文半徑 \(len_i\),此時這個回文半徑對應的回文串的實際長度是 \(len_i-1\)

因為要求的是兩個回文串拼起來,所以可以求 \(l_i,r_i\) 分表表示以 \(i\) 開頭,結尾的回文串最大長度,答案就是 \(\max\\)

當求出 \(len_i\) 時,這樣更新:\(l_=\max(l_,len_i-1),r_=\max(r_,len_i-1)\)

注意這裡 \(l,r\) 的下標是以填充後的字串下標為準,而值是在原有字串中的長度,也就是此時的 \(len_i-1\)

而我們要考慮的也只是當 \(s_i\) 是填充進來的字元時,\(l_i,r_i\) 的值,因為此時他才滿足向左向右都是原串的乙個回文子串

但,這樣只是更新了最大長度,比如對於 \(len_i',\(l_\) 也可以用 \(len_i'-1\) 來更新,但這裡並沒有更新到

所以做完 manacher 以後,還要分別對 \(l,r\) 處理:對於每乙個填充進來的 \(s_i\),\(l_i=\max(l_i,l_-2),r_i=\max(r_i,r_-2)\)

也就是以 \(i\) 開頭的,就考慮一下以 \(i-2\) 開頭的(上乙個填充進來的字元),用它的長度減去 \(2\)(減去一頭一尾)來更新。以 \(i\) 結尾的也是同理

最後考慮這些填充進來的 \(s_i\),取 \(\max\\) 為答案

#include#include#include#include#include#include#include#define reg register

#define en std::puts("")

#define ll long long

inline int read()

while(c>='0'&&c<='9')

return y?x:-x;

}char in[100005],s[200005];

int n;

int len[200005];

int l[200005],r[200005];

int main()

for(reg int i=1;i<=n;i+=2) l[i]=std::max(l[i],l[i-2]-2);

for(reg int i=n;i>0;i-=2) r[i]=std::max(r[i],r[i+2]-2);

reg int ans=0;

for(reg int i=1;i<=n;i+=2) ans=std::max(ans,(l[i]&&r[i])*(l[i]+r[i]));

printf("%d",ans);

return 0;

}

P4555 國家集訓隊 最長雙回文串

p4555 國家集訓隊 最長雙回文串 題目大意 求s的最長雙回文子串t,即可將t分為兩部分x,y,x y 1 且x和y都是回文串 建兩個回文自動機,乙個維護字首,乙個維護字尾 最後掃一遍更新答案 my complete code include include include includeusin...

最長雙回文串

題目描述 順序和逆序讀起來完全一樣的串叫做回文串。比如acbca是回文串,而abc不是 abc的順序為 abc 逆序為 cba 不相同 輸入長度為n的串s,求s的最長雙回文子串t,即可將t分為兩部分x,y,x y 1 且x和y都是回文串。對於 10 的資料,2 s 10 3 對於 30 的資料,2 ...

最長雙回文串

題目大意 輸入長度為n的串s,求s的最長雙回文子串t,即可將t分為兩部分x,y,x y 1 且x和y都是回文串。題解 若x,y都是回文串且相鄰,則共用乙個 可以對於每個 找出其左邊界和右邊界。include include include using namespace std define n 1...