hdu 2457 AC自动机DP

题意: 给出了一些病毒串的基因, 又给出了一个基因串,问至少修改多少个基因串中的字符可以不含病毒串。

思路: 这道题是用AC自动机搞的, 好久没写AC自动机了。

这道题的主要思路是构造基因串, 保证构造的基因串不含病毒串, 并且与给出的串相比修改的最少。

1、首先利用病毒串构造自动机, 但是需要注意两点,一是如果fall的结尾标记是病毒串的结尾,那么当前位置也要标记是病毒串的结尾。 如果next为-1, 那么一定要赋一个值,一般赋为fall的next,如果是root的话那就直接是root就行。将每个节点看成是一个状态。

2、进行DP, 对于初始化为INF的DP, 最好加一个continue, DP的过程其实是构造串的过程。

dp[i][j]表示构造到第i个字符的时候在j状态时需要修改的最小值。

 x = s[j].next[k]; x必须是可达状态
dp[i+1][x] = min( dp[i+1][x], dp[i][j] + (a[i+1]!=k) );

AC代码:

View Code
  1 #include<iostream>
  2 #include<queue>
  3 #include<cstring>
  4 #include<cstdio>
  5 using namespace std;
  6 const int N = 2010, INF = 1<<29;
  7 struct node
  8 {
  9     int f;
 10     int next[4];
 11     int fall;
 12     void init()
 13     {
 14         memset(next,-1,sizeof(next));
 15         fall = -1;
 16         f = 0;
 17     }
 18 } s[N];
 19 int p;
 20 char a[N];
 21 
 22 inline void preprocess()
 23 {
 24     s[p=0].init();
 25     s[0].fall = -1;
 26 }
 27 
 28 int get(char a)
 29  {
 30      if(a == 'A') return 0;
 31      if(a == 'C') return 1;
 32      if(a == 'G') return 2;
 33      return 3;
 34  }
 35 
 36 void insert(char *a)
 37 {
 38     int ind = 0;
 39     int i;
 40     for(i=0; a[i]; ++i)
 41     {
 42         int x=get(a[i]);
 43         if(s[ind].next[x]==-1)
 44         {
 45             s[++p].init();
 46             s[ind].next[x]=p;
 47         }
 48         ind = s[ind].next[x];
 49     }
 50     ++s[ind].f;
 51 }
 52 
 53 void build_ac()
 54 {
 55     int root=0;
 56     s[root].fall=-1;
 57     queue<int> q;
 58     q.push(root);
 59     while (!q.empty())
 60     {
 61         int t=q.front();
 62         q.pop();
 63         int i;
 64         for (i=0; i<4; ++i)
 65         {
 66             int ind = s[t].next[i];
 67             if(ind != -1)
 68              {
 69                 if (t == root)
 70                  {
 71                     s[ind].fall = root;
 72                  }
 73                 else
 74                  {
 75                     int p = s[t].fall;
 76                     while (p != -1)
 77                      {
 78                         if (s[p].next[i] != -1)
 79                         {
 80                             s[ind].fall = s[p].next[i];
 81                             int x = s[p].next[i];
 82                             if(s[x].f)
 83                              s[ind].f = 1;
 84                             break;
 85                         }
 86                         p = s[p].fall;
 87                      }
 88 
 89                     if (p == -1)
 90                      {
 91                         s[ind].fall = root;
 92                      }
 93                  }
 94                 q.push(ind);
 95              }
 96             else
 97              {
 98                  if(t == 0)
 99                   s[t].next[i] = 0;
100                  else
101                   {
102                       int x = s[t].fall;
103                       s[t].next[i] = s[x].next[i];
104                   }
105              }
106         }
107     }
108 }
109 
110 
111 int n, dp[N][N];
112 
113 int DP()
114  {
115      for(int i=0; i<=n; i++)
116       {
117           for(int j=0; j<=p; j++)
118            dp[i][j] = INF;
119       }
120     dp[0][0] = 0;
121     for(int i=0; i<n; i++)
122      {
123          for(int j=0; j<=p; j++)
124           {
125               if(dp[i][j] == INF) continue;
126               for(int k=0; k<4; k++)
127                {
128                    int x = s[j].next[k];
129                    if(s[x].f) continue;
130                    dp[i+1][x] = min(
131                             dp[i+1][x], dp[i][j] + (a[i+1]!=k) );
132                }
133           }
134      }
135     int ans = INF;
136     for(int i=0; i<=p; i++)
137      ans = min(ans, dp[n][i]);
138     if(ans == INF) return -1;
139     return ans;
140  }
141 
142 int main()
143 {
144     int test = 0;
145     while(scanf("%d", &n) != EOF && n)
146     {
147         test++;
148         preprocess();
149         for(int i=0; i<n; i++)
150         {
151            scanf("%s",a);
152            insert(a);
153         }
154         
155         scanf("%s",a+1);
156         n = strlen(a+1);
157         for(int i=1; i<=n; i++)
158          a[i] = get(a[i]);
159         build_ac();
160         printf("Case %d: %d\n", test, DP());
161     }
162     return 0;
163 }

 

    

你可能感兴趣的:(hdu 2457 AC自动机DP)