3 AC CG GT CGAT 1 AA AAA 0
Case 1: 3 Case 2: 2
题意:给定n个特定的串,最后给定一个串,让重新组合,使得含有的上面特定的串最多。
首先肯定需要建立ac自动机,然后就是dp,这道题在dp的时候需要一定的处理,不能直接搞,学习别人的思路,采用hash的方法,将死个字符出现的次数映射成数字,且保证了不会出现状态的重复,好神奇,然后就是一个dp的过程了。
代码:
/* *********************************************** Author :xianxingwuguan Created Time :2014-2-7 0:28:06 File Name :1.cpp ************************************************ */ #pragma comment(linker, "/STACK:102400000,102400000") #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #include <limits.h> #include <string> #include <time.h> #include <math.h> #include <queue> #include <stack> #include <set> #include <map> using namespace std; #define INF 0x3f3f3f3f #define eps 1e-8 #define pi acos(-1.0) typedef long long ll; struct Trie{ int next[550][4],fail[550],end[550]; int root,L; int newnode(){ for(int i=0;i<4;i++) next[L][i]=-1; end[L++]=0; return L-1; } void init(){ L=0; root=newnode(); } int id(char ch){ if(ch==‘A‘)return 0; if(ch==‘T‘)return 1; if(ch==‘C‘)return 2; return 3; } void insert(char *str){ int len=strlen(str); int now=root; for(int i=0;i<len;i++){ int p=id(str[i]); if(next[now][p]==-1) next[now][p]=newnode(); now=next[now][p]; } end[now]++; } void build(){ queue<int> q; fail[root]=root; for(int i=0;i<4;i++){ if(next[root][i]==-1) next[root][i]=root; else { fail[next[root][i]]=root; q.push(next[root][i]); } } while(!q.empty()){ int now=q.front(); q.pop(); end[now]+=end[fail[now]]; for(int i=0;i<4;i++){ if(next[now][i]==-1) next[now][i]=next[fail[now]][i]; else { fail[next[now][i]]=next[fail[now]][i]; q.push(next[now][i]); } } } } int dp[11*11*11*11+10][550]; int num[5],ss[5],hash[6]; int solve(char *str){ memset(hash,0,sizeof(hash)); memset(num,0,sizeof(num)); int len=strlen(str); for(int i=0;i<len;i++) num[id(str[i])]++; hash[3]=1; hash[2]=hash[3]*(num[3]+1); hash[1]=hash[2]*(num[2]+1); hash[0]=hash[1]*(num[1]+1); int t=hash[0]*num[0]+hash[1]*num[1]+hash[2]*num[2]+hash[3]*num[3]; memset(dp,-1,sizeof(dp)); int ans=dp[0][0]=0; for(int i=0;i<=t;i++){ ss[0]=i/hash[0]; ss[1]=(i%hash[0])/hash[1]; ss[2]=(i%hash[1])/hash[2]; ss[3]=(i%hash[2])/hash[3]; if(ss[0]>num[0]||ss[1]>num[1]||ss[2]>num[2]||ss[3]>num[3])continue; for(int j=0;j<L;j++){ if(dp[i][j]==-1)continue; for(int k=0;k<4;k++){ int tt=next[j][k]; if(ss[k]<num[k]&&dp[i+hash[k]][tt]<dp[i][j]+end[tt]) dp[i+hash[k]][tt]=dp[i][j]+end[tt]; } } } for(int i=0;i<L;i++) ans=max(ans,dp[t][i]); return ans; } }ac; char str[100010]; int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); int i,j,k,m,n,T=0; while(~scanf("%d",&n)){ if(n==0)break; ac.init(); while(n--){ scanf("%s",str); ac.insert(str); } ac.build(); scanf("%s",str); printf("Case %d: %d\n",++T,ac.solve(str)); } return 0; }
原文:http://blog.csdn.net/xianxingwuguan1/article/details/18955665