• poj 3691


    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 }
  • 相关阅读:
    获取移动端屏幕的宽度的方法
    document.body 与 document.documentElement区别介绍
    鼠标放上去会变化
    获取当前日期的函数
    侧边栏和右边高度的问题
    【Ajax】接收后台数据在html页面显示
    JS获取屏幕的大小
    python——字符串的方法及注释&字符串格式化符号含义及转义字符含义
    python——元组
    python——列表操作符
  • 原文地址:https://www.cnblogs.com/lj030/p/3101439.html
Copyright © 2020-2023  润新知