poj 3691

来源:互联网 发布:淘宝订单信息编辑 编辑:程序博客网 时间:2024/06/06 09:37

AC自动机的失配函数的利用和DP,Trie图中的每个节点代表一种状态,即一个字符串的后缀为从根节点到本节点的字符串。就是说把字符串根据他的后缀分为不同的类别,AC自动机上的每一个节点代表一个类别。在一个字符串的后面再加一个字符,此字符串就会从Tire图中的一个节点转移到另一个节点,这个过程可通过失配函数的求解过程中求出。其中有的节点所代表的类是不合法的,要记录下来。然后就是dp,ans[i][j]表示母串的i长度的串要变成状态为j的串所需最小修改次数。初始化为无穷大,如果j不合法不求,并且j的下一个转移得到的节点也不从j转移得到,最后比较每个节点的ans[len][j],得到最小值。

  1 #include <iostream>  2 #include <cstdio>  3 #include <cstring>  4 #include <queue>  5 using namespace std;  6 const int maxn=50+10;  7 const int inf=0x3f3f3f3f;  8 int n;  9 int ch[maxn*20][4]; 10 int val[maxn*20],tot,f[maxn*20]; 11 int ans[1000+10][maxn*20]; 12 int getV(char c) 13 { 14     switch(c) 15     { 16     case 'A':return 0; 17     case 'G':return 1; 18     case 'C':return 2; 19     case 'T':return 3; 20     } 21 } 22 void Insert(char *s) 23 { 24     int u=0,len=strlen(s),i,tv; 25     for(i=0;i<len;i++) 26     { 27         tv=getV(s[i]); 28         if(!ch[u][tv]) ch[u][tv]=tot++; 29         u=ch[u][tv]; 30     } 31     val[u]=1; 32 } 33 void getFail() 34 { 35     queue<int> q; 36     f[0]=0; 37     int i,u; 38     for(i=0;i<4;i++) 39     { 40         u=ch[0][i]; 41         if(u) 42         { 43             f[u]=0; 44             q.push(u); 45             //printf("%d %d\n",u,val[u]); 46         } 47     } 48     int v,r; 49     while(!q.empty()) 50     { 51         r=q.front();q.pop(); 52         for(i=0;i<4;i++) 53         { 54             u=ch[r][i]; 55             if(!u) { ch[r][i]=ch[f[r]][i]; } 56             else 57             { 58             if(val[r]) val[u]=1;//这部很关键 59             q.push(u); 60             v=f[r]; 61             while(v&&!ch[v][i]) v=f[v]; 62             f[u]=ch[v][i]; 63             if(val[f[u]]) val[u]=1;//这步很关键 64             } 65          //   printf("%d %d\n",u,val[u]); 66         } 67     } 68 } 69 int main() 70 { 71     int cas=0; 72     while(scanf("%d",&n)&&n) 73     { 74         int i,j; 75         char s[1000+10]; 76         tot=1; 77         memset(ch,0,sizeof(ch)); 78         memset(val,0,sizeof(val)); 79         for(i=0;i<n;i++) 80         { 81             scanf("%s",s); 82             Insert(s); 83         } 84         scanf("%s",s); 85         getFail(); 86         int len=strlen(s); 87         for(i=0;i<=len;i++) 88         { 89             for(j=0;j<tot;j++) 90                 ans[i][j]=inf; 91         } 92         ans[0][0]=0; 93         int k,v; 94         for(i=0;i<len;i++) 95         { 96             for(j=0;j<tot;j++) 97             { 98                 if(ans[i][j]<inf) 99                 {100                 for(k=0;k<4;k++)101                 {102                     if(!val[ch[j][k]])103                     {104                         v=ch[j][k];105                         ans[i+1][v]=min(ans[i+1][v],ans[i][j]+(getV(s[i])==k?0:1));106                     }107                 }108             }109             }110         }111         int re=inf;112         for(i=0;i<tot;i++) re=min(re,ans[len][i]);113         printf("Case %d: %d\n",++cas,re<inf?re:-1);114     }115     return 0;116 }

 

原创粉丝点击