BZOJ 2565 最長迴文串
阿新 • • 發佈:2018-12-22
傳送門
迴文自動機!
正著跑一遍 記錄以每個點作為迴文子串的右端點的最大長度
倒過來跑一遍 記錄每個點作為左端點的最大長度
求個和就好啦
附程式碼。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define inf 20021225 #define ll long long #define mxn 100010 using namespace std; struct node{int fa,ch[26],len;}t[mxn]; int poi,lt,f[mxn],s[mxn],n,len,ans; char ch[mxn]; void init() { memset(s,0,sizeof(s)); for(int i=0;i<=poi;i++) memset(t[i].ch,0,sizeof(t[i].ch)),t[i].fa=t[i].len=0; s[0] = -1; t[1].fa = t[0].fa =1; t[1].len = -1; t[0].len = 0; poi = lt = 1; n=0; } int id(char c){return c-'a';} void extend(int c,int b,int id) { //printf("%d\n",c); int p = lt; s[++n] = c; while(s[n-1-t[p].len]!=c) p=t[p].fa; if(!t[p].ch[c]) { int q = ++poi; t[q].len = t[p].len+2; int np = t[p].fa; while(s[n-1-t[np].len]!=c) np = t[np].fa; t[q].fa = t[np].ch[c]; t[p].ch[c] = q; } lt = t[p].ch[c]; if(b) f[id+1] = t[lt].len; else ans=max(f[id]+t[lt].len,ans); } int main() { scanf("%s",ch); len = strlen(ch); init(); for(int i=0;i<len;i++) extend(id(ch[i]),1,i); init(); for(int i=len-1;~i;i--) extend(id(ch[i]),0,i); printf("%d\n",ans); return 0; }
這玩意跑的奇快無比。