HDU 3341

Qinz的题。。。

题意: 给定AGTC的数目,求组成的串中能含给定的串最大数目;trick可以有一样的给定串,但是要算两次。题目不严谨呀^_^;

 

之前自动机只是局限于入门级的题。这回在构建auto时,每个节点的next都有值;这和之前统计的计数不一样了。

 

看到网上好多dfs,感觉效率不高,其实就是个背包。自动机充当了状态转移的工具。

 

代码效率不是很高。2900ms。但也不低。。。。。。

 

代码贴之:

 

#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int MAXN=550; const int ST=8000; int hash[255]; int limt[4]; int bin[4]; int cnt,i,j,k; int que[MAXN]; int dp[20000][MAXN]; struct node{ int next[4]; int danger; int fail; node(){ memset(next,0,sizeof(next)); danger=0; } } tire[MAXN]; void insert(char *s){ int p=1; for(i=0; s[i]; ++i){ if(tire[p].next[hash[s[i]]]==0){ tire[p].next[hash[s[i]]]=++cnt; p=cnt; } else p=tire[p].next[hash[s[i]]]; } ++tire[p].danger; } void build_ac(){ int h=0,t=1,now,p; que[0]=1; tire[1].fail=-1; while(h<t){ now=que[h++]; for(i=0; i<4; ++i){ if(tire[now].next[i]!=0){ p=tire[now].fail; if(p==-1) tire[tire[now].next[i]].fail=1; else{ while(p!=1&&!tire[p].next[i]) p=tire[p].fail; if(p==-1) tire[tire[now].next[i]].fail=1; else{ tire[tire[now].next[i]].fail=tire[p].next[i]; tire[tire[now].next[i]].danger+=tire[tire[p].next[i]].danger; } } que[t++]=tire[now].next[i]; } else{ p=tire[now].fail; while(p!=-1&&!tire[p].next[i]) p=tire[p].fail; if(p==-1) tire[now].next[i]=1; else tire[now].next[i]=tire[p].next[i]; } } } } int ans(char *s){ int res=0; int p=0; i=0; while(s[i]){ if(p==-1) { ++i; p=0; continue;} if(tire[p].next[hash[s[i]]]){ p=tire[p].next[hash[s[i]]]; ++i; res+=tire[p].danger; } else{ p=tire[p].fail; } } return res; } int main(){ int test; int ttt=0; // scanf("%d",&test); while(1){ char tmp[12]; memset(tire,0,sizeof(tire)); cnt=1; int t; hash['A']=0,hash['T']=1,hash['G']=2,hash['C']=3; scanf("%d",&t); if(t==0) break; while(t--){ scanf("%s",tmp); insert(tmp); } build_ac(); /* char msg[100]; scanf("%s",msg); printf("%d/n",ans(msg)); system("pause"); */ memset(limt,0,sizeof(limt)); memset(dp,-1,sizeof(dp)); char msg[100]; scanf("%s",msg); for(i=0; msg[i]; ++i){ ++limt[hash[msg[i]]]; } bin[0]=(limt[1]+1)*(limt[2]+1)*(limt[3]+1); bin[1]=(limt[2]+1)*(limt[3]+1); bin[2]=(limt[3]+1); bin[3]=1; dp[0][1]=0; for(int i1=0; i1<=limt[0]; ++i1) for(int i2=0; i2<=limt[1]; ++i2) for(int i3=0; i3<=limt[2]; ++i3) for(int i4=0; i4<=limt[3]; ++i4) for(int i5=1; i5<=cnt; ++i5) { int tt=i1*bin[0]+i2*bin[1]+i3*bin[2]+i4; if(i1-1>-1&&dp[tt-bin[0]][i5]!=-1) dp[tt][tire[i5].next[0]]=max(dp[tt][tire[i5].next[0]],dp[tt-bin[0]][i5]+tire[tire[i5].next[0]].danger); if(i2-1>-1&&dp[tt-bin[1]][i5]!=-1) dp[tt][tire[i5].next[1]]=max(dp[tt][tire[i5].next[1]],dp[tt-bin[1]][i5]+tire[tire[i5].next[1]].danger); if(i3-1>-1&&dp[tt-bin[2]][i5]!=-1) dp[tt][tire[i5].next[2]]=max(dp[tt][tire[i5].next[2]],dp[tt-bin[2]][i5]+tire[tire[i5].next[2]].danger); if(i4-1>-1&&dp[tt-bin[3]][i5]!=-1) dp[tt][tire[i5].next[3]]=max(dp[tt][tire[i5].next[3]],dp[tt-bin[3]][i5]+tire[tire[i5].next[3]].danger); } int ANS=-1; for(i=1; i<=cnt; ++i) ANS=max(ANS,dp[limt[0]*bin[0]+limt[1]*bin[1]+limt[2]*bin[2]+limt[3]*bin[3]][i]); printf("Case %d: %d/n",++ttt,ANS); } //system("pause"); }  

你可能感兴趣的:(HDU 3341)