回文自动机学习笔记

毛子牛逼!

回文自动机

 1 //bzoj4044
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 int q,_len,son[100010][4],len[100001],f[100001],fail[100001],pre[100001],num[100001],st[100001],tot,n,last,ans;
 9 char s[100001];
10 int u(char ch){
11     return ch=='A'?0:ch=='T'?1:ch=='C'?2:3;
12 }
13 int newnode(int l){
14     for(int i=0;i<4;i++)son[tot][i]=0;
15     len[tot]=l;
16     return tot++;
17 }
18 void init(){
19     tot=n=last=0;
20     newnode(0);
21     newnode(-1);
22     fail[0]=1;
23     st[0]=-1;
24 }
25 int get_fail(int u){
26     while(st[n-len[u]-1]!=st[n])u=fail[u];
27     return u;
28 }
29 void ins(int c){
30     st[++n]=c;
31     int now=get_fail(last);
32     if(!son[now][c]){
33         int newn=newnode(len[now]+2);
34         fail[newn]=son[get_fail(fail[now])][c];
35         if(len[newn]<=2)pre[newn]=fail[newn];
36         else{
37             int v=pre[now];
38             while(st[n-len[v]-1]!=st[n]||(len[v]+2)*2>len[newn])v=fail[v];
39             pre[newn]=son[v][c];
40         }
41         son[now][c]=newn;
42     }
43     last=son[now][c];
44 }
45 void dp(){
46     int u,v;
47     queue<int>q;
48     for(int i=2;i<tot;i++){
49         if(len[i]%2==1)f[i]=len[i];
50     }
51     q.push(0);
52     f[0]=1;
53     while(!q.empty()){
54         u=q.front();
55         q.pop();
56         for(int i=0;i<4;i++){
57             if(son[u][i]){
58                 v=son[u][i];
59                 f[v]=min(f[u]+1,len[v]/2-len[pre[v]]+f[pre[v]]+1);
60                 ans=min(ans,_len-len[v]+f[v]);
61                 q.push(v);
62             }
63         }
64     }
65 }
66 int main(){
67     scanf("%d",&q);
68     while(q--){
69         scanf("%s",s);
70         init();
71         ans=_len=strlen(s);
72         for(int i=0;i<_len;i++){
73             ins(u(s[i]));
74         }
75         dp();
76         printf("%d
",ans);
77     }
78     return 0;
79 }
原文地址:https://www.cnblogs.com/dcdcbigbig/p/9222929.html