Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1010 Accepted Submission(s): 274
题目:给出一些模式串,每个串有一定的价值,现在构造一个长度为M的串,问最大的价值为多少,每个模式串最多统计一次。
由于每个模式串最多统计一次,也算是降低了难度,最多10个串,容易想至于状态压缩。
Trie树上的状态最多1000个,100*10,而最终的串长度最多为100
容易想到的DP,dp[i][j][k],表示长度为i的串,位于Trie上的状态j,模式串的状态为k的最大价值。
这个复杂度为100*1024*1000,题目给了10s,还是可以搞的,但是空间不够,只能用滚动数组了。
先建立Trie树,以及失败指针,对于每一个结点,标号,静态的方便点。
最终DP,通过模式串的状态确定当前价值
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=100010; const int INF=0x3f3f3f3f; struct Trie{ int count; int fail,next[4]; void init(){ memset(next,0,sizeof(next)); fail=count=0; } }tree[N]; int cnt,val[N],dp[2][1010][1<<10]; char str[110]; int find(char ch){ switch(ch){ case 'A':return 0; case 'T':return 1; case 'C':return 2; case 'G':return 3; } return 0; } void Insert(char *str,int k){ int i=0,loc=0; while(str[i]!='\0'){ int id=find(str[i]); if(tree[loc].next[id]==0){ tree[++cnt].init(); tree[loc].next[id]=cnt; } loc=tree[loc].next[id]; i++; } tree[loc].count |= (1<<k); } void AC_automation(){ int que[N]; int head=0,tail=0; que[tail++]=0; while(head<tail){ int cur=que[head++]; for(int i=0;i<4;i++){ if(tree[cur].next[i]==0) tree[cur].next[i]=tree[tree[cur].fail].next[i]; else{ int tmp=tree[cur].next[i]; if(cur) tree[tmp].fail=tree[tree[cur].fail].next[i]; tree[tmp].count |= tree[tree[tmp].fail].count; que[tail++]=tmp; } } } } int n,m; int get(int state){ int ans=0; for(int i=0;i<n;i++) if(state&(1<<i)) ans+=val[i]; return ans; } void DP(){ memset(dp,0,sizeof(dp)); dp[0][0][0]=1; for(int i=1;i<=m;i++){ memset(dp[i&1],0,sizeof(dp[i&1])); for(int j=0;j<=cnt;j++) for(int k=0;k<4;k++) for(int r=0;r<(1<<n);r++) if(dp[(i+1)&1][j][r]) dp[i&1][tree[j].next[k]][r|tree[tree[j].next[k]].count]=1; } int ans=-INF; for(int j=0;j<(1<<n);j++) for(int i=0;i<=cnt;i++) if(dp[m&1][i][j]){ ans=max(ans,get(j)); break; } if(ans<0) puts("No Rabbit after 2012!"); else printf("%d\n",ans); } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d%d",&n,&m)){ tree[0].init(); cnt=0; for(int i=0;i<n;i++){ scanf("%s%d",str,&val[i]); Insert(str,i); } AC_automation(); DP(); } return 0; }