• POJ 3691 TRIE图+DP


    题意:

    已知一个DNA串和一些病毒DNA序列,求出最少改变DNA串中多少个字符,能使得串中不包含任意一个病毒序列。

    题解:

    嗯,和上一个trie图一样,把病毒建成trie,只要母串不能再trie上走到危险节点即可(危险节点就是病毒dna序列的终止的那个被标有fg的节点)。

    然后trie图上的dp,要走到危险节点的时候,枚举转移即可。

    View Code
     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 #include <cstdlib>
     5 #include <algorithm>
     6 
     7 #define M 1111
     8 #define N 111
     9 #define INF 0x3f3f3f3f
    10 
    11 using namespace std;
    12 
    13 struct TR
    14 {
    15     int son[4]; int f; bool fg;
    16 }tr[N*N];
    17 
    18 int map[N],cnt,q[N*N],n,m,cas;
    19 char str[N],a[M];
    20 int dp[M][N*N];
    21 
    22 inline void insert(char *s)
    23 {
    24     int len=strlen(s+1);
    25     int now=1;
    26     for(int i=1;i<=len;i++)
    27     {
    28         if(!tr[now].son[map[s[i]]]) tr[now].son[map[s[i]]]=++cnt;
    29         now=tr[now].son[map[s[i]]];
    30     }
    31     tr[now].fg=true;
    32 }
    33 
    34 inline void build()
    35 {
    36     int h=1,t=2,sta,now,tmp;
    37     q[1]=1;
    38     while(h<t)
    39     {
    40         sta=q[h++];
    41         for(int i=0;i<4;i++)
    42         {
    43             now=tr[sta].son[i];
    44             if(sta==1) tmp=1;
    45             else tmp=tr[tr[sta].f].son[i];
    46             if(now==0) tr[sta].son[i]=tmp;
    47             else
    48             {
    49                 tr[now].f=tmp; tr[now].fg|=tr[tmp].fg;
    50                 q[t++]=now;
    51             }
    52         }
    53     }
    54 }
    55 
    56 inline void read()
    57 {
    58     memset(tr,0,sizeof tr);
    59     tr[cnt=1].f=1;
    60     for(int i=1;i<=n;i++)
    61     {
    62         scanf("%s",str+1);
    63         insert(str);
    64     }
    65     scanf("%s",a+1);
    66     m=strlen(a+1);
    67     build();
    68 }
    69 
    70 inline void go()
    71 {
    72     memset(dp,0x3f,sizeof dp);
    73     dp[0][1]=0;
    74     for(int i=0;i<m;i++)
    75         for(int j=1;j<=cnt;j++)
    76         {
    77             for(int k=0;k<4;k++)
    78                 if(!tr[tr[j].son[k]].fg) dp[i+1][tr[j].son[k]]=min(dp[i+1][tr[j].son[k]],dp[i][j]+1);
    79             if(!tr[tr[j].son[map[a[i+1]]]].fg) dp[i+1][tr[j].son[map[a[i+1]]]]=min(dp[i+1][tr[j].son[map[a[i+1]]]],dp[i][j]);
    80         }
    81     int ans=INF;
    82     for(int i=1;i<=cnt;i++) ans=min(ans,dp[m][i]);
    83     if(ans==INF) ans=-1;
    84     printf("Case %d: %d\n",++cas,ans);
    85 }
    86 
    87 int main()
    88 {
    89     map['A']=0; map['G']=1; map['C']=2; map['T']=3;
    90     while(scanf("%d",&n),n) read(),go();
    91     return 0;
    92 }
  • 相关阅读:
    3D照片放大展示窗口
    [NOI2015]品酒大会
    [SDOI2016]排列计数
    [SCOI2008]奖励关
    HDU4336 Card Collector
    CF540D Bad Luck Island
    [NOI2016]网格
    HDU3076 ssworld VS DDD
    [USACO10HOL]赶小猪
    CF113D Museum
  • 原文地址:https://www.cnblogs.com/proverbs/p/2945092.html
Copyright © 2020-2023  润新知