BZOJ2565 最长双回文子串 回文自动机,回文树
bzoj2565: 最長(zhǎng)雙回文串
題意
順序和逆序讀起來(lái)完全一樣的串叫做回文串。比如acbca是回文串,而abc不是(abc的順序?yàn)椤癮bc”,逆序?yàn)椤癱ba”,不相同)。
輸入長(zhǎng)度為n的串S,求S的最長(zhǎng)雙回文子串T,即可將T分為兩部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。 N<=100000。
?
這道題可以用manacher算法解決,但是用manacher解決問(wèn)題的同時(shí),有可能需要計(jì)算長(zhǎng)度的關(guān)系,可能會(huì)出現(xiàn)混亂。在這里采用更清楚的回文自動(dòng)機(jī);
在做這道題之前需要掌握的知識(shí)是回文自動(dòng)機(jī)的實(shí)現(xiàn)和作用,如果有不了解算法的同志,請(qǐng)自行翻大神博客進(jìn)行學(xué)習(xí):
https://www.cnblogs.com/crazyacking/p/5234823.html
在這里,由于是要找兩個(gè)回文串,還必須是相鄰的,所以我們可以通過(guò)把整串翻轉(zhuǎn)的方法實(shí)現(xiàn)求相鄰回文串,根據(jù)回文樹(shù)的作用,可以求出以下標(biāo)i結(jié)尾的最長(zhǎng)回文字符串,注意是以下標(biāo)i結(jié)尾的最長(zhǎng)串,而不是開(kāi)始,不理解的話可以自己模擬一下字符加進(jìn)回文自動(dòng)機(jī)形成回文自動(dòng)機(jī)的那些步驟,求出來(lái)之后可以枚舉相鄰的那個(gè)點(diǎn)來(lái)進(jìn)行轉(zhuǎn)移,求出最長(zhǎng)的雙回文串,這道題就結(jié)束了,現(xiàn)在上代碼:
?
1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<cstring> 7 #include<string> 8 #include<queue> 9 using namespace std; 10 const int MAXN=100005; 11 int nxt[MAXN][26],fail[MAXN],len[MAXN],num[MAXN],cnt[MAXN],mx1[MAXN],mx2[MAXN]; 12 int n,m,k,l,r,last,p=0; 13 char s[MAXN],ops[MAXN]; 14 inline int getfail(int x) 15 { 16 while(s[n-len[x]-1]!=s[n]) x=fail[x]; 17 return x; 18 } 19 inline void add(int x,int i,int *mx) 20 { 21 last=getfail(last); 22 if(nxt[last][x]==0){ 23 len[++p]=len[last]+2; 24 fail[p]=nxt[getfail(fail[last])][x]; 25 nxt[last][x]=p; 26 num[p]=num[fail[p]]+1; 27 } 28 last=nxt[last][x]; 29 mx[i]=len[last]; 30 cnt[last]++; 31 return ; 32 } 33 int main() 34 { 35 scanf("%s",s+1); 36 m=strlen(s+1); 37 p=last=n=0; 38 len[++p]=-1; 39 fail[0]=p; 40 for(int i=1;i<=m;i++){ 41 n++; 42 add(s[i]-'a',i,mx1); 43 } 44 memset(fail,0,sizeof(fail)); 45 memset(cnt,0,sizeof(cnt)); 46 memset(num,0,sizeof(num)); 47 memset(len,0,sizeof(len)); 48 memset(nxt,0,sizeof(nxt)); 49 p=last=n=0;len[++p]=-1;fail[0]=p; 50 for(int i=1;i<=m;i++){ 51 ops[i]=s[m-i+1]; 52 } 53 for(int i=1;i<=m;i++){ 54 s[i]=ops[i]; 55 } 56 for(int i=1;i<=m;i++){ 57 n++; 58 add(s[i]-'a',i,mx2); 59 } 60 int ans=-1; 61 for(int i=1;i<=m;i++){ 62 ans=max(ans,mx1[i]+mx2[m-i+0]); 63 } 64 cout<<ans<<endl; 65 return 0; 66 }?
轉(zhuǎn)載于:https://www.cnblogs.com/Alan-Luo/articles/9160813.html
總結(jié)
以上是生活随笔為你收集整理的BZOJ2565 最长双回文子串 回文自动机,回文树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 百度阿里网易大疆等大小厂前端校招面筋 |
- 下一篇: 我的博客园css样式