2 AAA AAG AAAG 2 A TG TGAATG 4 A G C T AGT 0
Case 1: 1 Case 2: 4 Case 3: -1
给你一个串,只包含ATCG,最少修改几个位置能让这个串不包含上面给的串,如果不能输出-1。
dp[i][u]表示这个串的前i个字母走到节点u的最少修改次数,有标记的节点不能走,很简单的DP了。
#include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> #include<queue> using namespace std; typedef unsigned long long ULL; const int MAXN=55; const int MAXM=25; const int MAXL=1010; const int MAXNODE=MAXN*MAXM; const int LOGMAXN=50; const int INF=0x3f3f3f3f; const int SIGMA_SIZE=4; const int MOD=20090717; int T,N; char str[MAXM]; char P[MAXL]; int dp[MAXL][MAXNODE]; struct AC{ int ch[MAXNODE][SIGMA_SIZE]; int val[MAXNODE]; int f[MAXNODE]; int sz; void clear(){ memset(ch[0],0,sizeof(ch[0])); val[0]=0; sz=1; } int idx(char c){ switch(c){ case 'A':return 0; case 'G':return 1; case 'C':return 2; case 'T':return 3; } } void insert(char* s,int v){ int u=0; for(int i=0;s[i];i++){ int c=idx(s[i]); if(!ch[u][c]){ memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=v; } void get_fail(){ queue<int> q; f[0]=0; for(int c=0;c<SIGMA_SIZE;c++){ int u=ch[0][c]; if(u){ f[u]=0; q.push(u); } } while(!q.empty()){ int r=q.front(); q.pop(); for(int c=0;c<SIGMA_SIZE;c++){ int u=ch[r][c]; if(!u){ ch[r][c]=ch[f[r]][c]; continue; } q.push(u); f[u]=ch[f[r]][c]; val[u]|=val[f[u]]; } } } }ac; void DP(){ int len=strlen(P); memset(dp,INF,sizeof(dp)); dp[0][0]=0; for(int i=0;i<len;i++) for(int u=0;u<ac.sz;u++) if(dp[i][u]!=INF){ for(int c=0;c<SIGMA_SIZE;c++) if(!ac.val[ac.ch[u][c]]){ if(ac.idx(P[i])==c) dp[i+1][ac.ch[u][c]]=min(dp[i+1][ac.ch[u][c]],dp[i][u]); else dp[i+1][ac.ch[u][c]]=min(dp[i+1][ac.ch[u][c]],dp[i][u]+1); } } int ans=INF; for(int i=0;i<ac.sz;i++) ans=min(ans,dp[len][i]); if(ans==INF) printf("-1\n"); else printf("%d\n",ans); } int main(){ freopen("in.txt","r",stdin); int cas=0; while(scanf("%d",&N)!=EOF&&N){ ac.clear(); for(int i=1;i<=N;i++){ scanf("%s",str); ac.insert(str,1); } ac.get_fail(); scanf("%s",P); printf("Case %d: ",++cas); DP(); } return 0; }