POJ-3691 DNA repair AC自动机+DP

  题目链接:http://poj.org/problem?id=3691

  首先庆祝1A。

    如果是单串的匹配,那么状态转移方程就是f[i][j],表示匹配串的前 i 位最近9个数字的状态是 j 的最小改动,每个状态用状态压缩表示下就可以了。复杂度是指数级,对于较小的字符串还是可以接受的。但是这个有很多不必要的情况,因为很多转移都可以归纳到一起,即修改或者不修改,因此把方程改为表示匹配串的第 i 为模板串的第 j 个节点时的最优解,那么对于每个节点就只有4种转移状态了,即一个单串的DFA。同样,我们对于多个串建立一个AC自动机就可以了,转移方程:f[i][j]=Min{ f[i][j] , f[i][son] + c!=id }。

  注意要考虑当前串的字串是不合法串的情况。

  1 //STATUS:C++_AC_79MS_4200KB

  2 #include<stdio.h>

  3 #include<stdlib.h>

  4 #include<string.h>

  5 #include<math.h>

  6 #include<iostream>

  7 #include<string>

  8 #include<algorithm>

  9 #include<vector>

 10 #include<queue>

 11 #include<stack>

 12 #include<map>

 13 #include<set>

 14 using namespace std;

 15 //define

 16 #define pii pair<int,int>

 17 #define mem(a,b) memset(a,b,sizeof(a))

 18 #define lson l,mid,rt<<1

 19 #define rson mid+1,r,rt<<1|1

 20 #define PI acos(-1.0)

 21 //typedef

 22 typedef __int64 LL;

 23 typedef unsigned __int64 ULL;

 24 //const

 25 const int N=1010;

 26 const int INF=0x3f3f3f3f;

 27 const int MOD=100000,STA=8000010;

 28 const LL LNF=1LL<<60;

 29 const double EPS=1e-8;

 30 const double OO=1e15;

 31 //Daily Use ...

 32 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}

 33 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}

 34 template<class T> inline T Min(T a,T b){return a<b?a:b;}

 35 template<class T> inline T Max(T a,T b){return a>b?a:b;}

 36 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}

 37 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}

 38 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}

 39 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}

 40 //End

 41 

 42 char s[N];

 43 int idx[100];

 44 int ch[N][4];

 45 int val[N],f[N],dp[N][N],sta[N],ma[N];

 46 int sz,n,cnt;

 47 

 48 void init(){sz=1;mem(ch[0],0);}

 49 

 50 void insert(char *s,int v){

 51     int i,len=strlen(s),id,u=0;

 52     for(i=0;i<len;i++){

 53         id=idx[s[i]];

 54         if(!ch[u][id]){

 55             mem(ch[sz],0);

 56             val[sz]=0;

 57             ch[u][id]=sz++;

 58         }

 59         u=ch[u][id];

 60     }

 61     val[u]=v;

 62 }

 63 

 64 void getFail()

 65 {

 66     int c,u,r;

 67     queue<int> q;

 68     f[0]=0;

 69     ma[0]=0;sta[0]=cnt++;

 70     for(c=0;c<4;c++){

 71         u=ch[0][c];

 72         if(u){

 73             if(!val[u])ma[u]=cnt;sta[cnt++]=u;

 74             f[u]=0;

 75             q.push(u);

 76         }

 77     }

 78     while(!q.empty()){

 79         r=q.front();q.pop();

 80         for(c=0;c<4;c++){

 81             u=ch[r][c];

 82             if(!u){

 83                 ch[r][c]=ch[f[r]][c];

 84                 continue;

 85             }

 86             q.push(u);

 87             f[u]=ch[f[r]][c];

 88             if(val[r] || val[f[u]])val[u]=1;

 89             if(!val[u]){ma[u]=cnt;sta[cnt++]=u;}

 90         }

 91     }

 92 }

 93 

 94 int main()

 95 {

 96  //   freopen("in.txt","r",stdin);

 97     int i,j,t,c,test=1,ans,len,ok,id,u;

 98     char temp[23];

 99     idx['A']=0;idx['C']=1;idx['T']=2,idx['G']=3;

100     while(~scanf("%d",&n) && n)

101     {

102         init();

103         for(i=0;i<n;i++){

104             scanf("%s",temp);

105             insert(temp,1);

106         }

107         scanf("%s",s);

108         len=strlen(s);

109 

110         cnt=0;

111         mem(dp,INF);

112         dp[0][0]=0;

113         getFail();

114         for(i=0;i<len;i++){

115             ok=0;

116             id=idx[s[i]];

117             for(j=0;j<cnt;j++){

118                 if(dp[i][j]==INF)continue;

119                 for(c=0;c<4;c++){

120                     u=ch[sta[j]][c];

121                     t=(c!=id);

122                     if(!val[u]){

123                         ok=1;

124                         dp[i+1][ma[u]]=Min(dp[i+1][ma[u]],dp[i][j]+t);

125                     }

126                 }

127             }

128             if(!ok)break;

129         }

130 

131         if(ok){

132             ans=INF;

133             for(i=0;i<cnt;i++){

134                 ans=Min(ans,dp[len][i]);

135             }

136         }

137         else ans=-1;

138 

139         printf("Case %d: %d\n",test++,ans);

140     }

141     return 0;

142 }

 

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