bzoj4044 [Cerc2014] Virus synthesis

回文自动机上dp

f[x]表示形成x代表的回文串所需的最小步数,

若len[x]为奇数,f[x]=len[x],因为即使有更优的,也是直接添加,没有复制操作,那样就不用从x转移了。

若len[x]为偶数,f[x]=min(f[fa[x]]+1,len[x]/2-len[fro[x]]+f[fro[x]]+1),因为fa[x]肯定是最后复制更优,那么将复制前的子串末尾加一个字符即可,fro则是len不大于len[x]/2的最长的x的fail.

memsetT死了,改成每次只memset用的就过了

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define N 100050
 5 using namespace std;
 6 int len[N],ch[N][5],nxt[N],fro[N],f[N];
 7 int T,n,ans,last,tot;
 8 char s[N];
 9 inline void init(){
10     ans=0x7fffffff;
11     last=0;tot=1;
12     memset(ch[0],0,sizeof ch[0]);
13     memset(ch[1],0,sizeof ch[1]);
14     nxt[0]=nxt[1]=1;
15     len[1]=-1;
16 }
17 inline int getfail(int x,int en){
18     while(s[en]!=s[en-len[x]-1])x=nxt[x];
19     return x;
20 }
21 inline void insert(int t,int en){
22     int now=getfail(last,en);
23     if(!ch[now][t]){
24         int x=++tot;
25         memset(ch[x],0,sizeof ch[x]);
26         len[x]=len[now]+2;
27         int fa=getfail(nxt[now],en);
28         nxt[x]=ch[fa][t];
29         fa=fro[now];
30         if(len[x]<=2)fro[x]=0;
31         else{
32             while(s[en]!=s[en-len[fa]-1]||(len[fa]+2)*2>len[x])
33                 fa=nxt[fa];
34             fro[x]=ch[fa][t];
35         }
36         if(len[x]&1||len[x]<=2)f[x]=len[x];
37         else f[x]=min(f[now]+1,len[x]/2-len[fro[x]]+f[fro[x]]+1);
38         ans=min(ans,n-len[x]+f[x]);
39         ch[now][t]=x;
40     }
41     last=ch[now][t];
42 }
43 int hash(char x){
44     if(x=='A')return 0;
45     if(x=='T')return 1;
46     if(x=='C')return 2;
47     return 3;
48 }
49 void work(){
50     init();
51     scanf("%s",s);
52     n=strlen(s);
53     for(int i=0;i<n;i++)
54         insert(hash(s[i]),i);
55     printf("%d\n",ans);
56 }
57 int main(){
58     scanf("%d",&T);
59     while(T--)work();
60     return 0;
61 }
View Code

 

posted @ 2018-01-03 16:29  Ren_Ivan  阅读(184)  评论(0编辑  收藏  举报