\(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...