题意:给若干种个串,再给个主串,然后把主串打乱顺序,使得包含子串尽量多(一种可以有多个,两个之间可以部分重叠)。如第一组数据,ACGT,包含AC、CG、GT,三个,输出3。第二组数据A1A2A3,包含A1A2和A2A3两个“AA”,答案为2。
其实我并没有AC。我被卡常数TLE了。。。实在不想写这种没意义的东西了。
贴代码,待填坑。
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #define max(a,b) (a>b?a:b) #define N 41 #define P 505 #define M 15000// 14641 #define T 4 #define inf 0x3f3f3f3f using namespace std; char ttt[50]; int f[P][M],g[P][M],crs[200]; int cn[5],mul[5],ed; struct ACAUTO { int next[P][T],num[P],fail[P],cnt,stack[P]; queue<int>q; void init() { while(!q.empty())q.pop(); memset(num,0,sizeof(num)); memset(fail,0,sizeof(fail)); } void insert() { static int i,x,alp; x = 0; scanf("%s",ttt); for(i=0;ttt[i];i++) { alp=crs[ttt[i]]; if(!next[x][alp])next[x][alp]=++cnt; x=next[x][alp]; } ++num[x]; } bool build() { int n,i,u,v,temp; int tcnt=0; scanf("%d",&n); if(!n)return 0; init(); for(i=1;i<=n;++i)insert(); q.push(0); while(!q.empty())/*維護fail指針*/ { // static int _ = 0; // cout << ++_ << endl; u=q.front(),q.pop(); stack[++tcnt]=u; for(i=0;i<T;++i)if(v=next[u][i]) { if(u) { temp=fail[u]; while(temp&&!next[temp][i])temp=fail[temp]; fail[v]=next[temp][i]; num[v]+=num[fail[v]]; } q.push(v); } } return 1; } void dp() { int i,j,u,v; int zt; for(u=0;u<=cnt;u++) { for(i=0;i<ed;i++) { for(j=0;j<T;j++)if(next[u][j]&&((j?i%mul[j-1]:i)/mul[j]+1)<cn[j]) { v=next[u][j]; zt=i+mul[j]; f[v][zt]=max(f[v][zt],g[u][i]+num[v]); // f[v][zt]=max(f[v][zt],f[u][i]+num[v]); } } } for(i=cnt+1;i;i--) { u=stack[i]; v=fail[u]; // for(j=0;j<ed;j++)f[v][j]=max(f[v][j],f[u][j]); for(j=0;j<ed;j++)g[u][j]=max(g[u][j],f[u][j]),g[v][j]=max(g[v][j],g[u][j]); } } }acauto; void work(int cas) { int i,j,k; scanf("%s",ttt); memset(cn,0,sizeof(cn)); memset(f,0xc0,sizeof(f)); memset(g,0xc0,sizeof(g)); f[0][0]=g[0][0]=0; for(i=0;ttt[i];i++)cn[crs[ttt[i]]]++; for(i=0;i<T;i++)cn[i]++; for(mul[T-1]=1,i=T-2;i>=0;i--)mul[i]=cn[i+1]*mul[i+1]; ed=cn[0]*cn[1]*cn[2]*cn[3]; int ans=0,llen=strlen(ttt); for(i=0;i<llen;i++) acauto.dp(); for(i=0;i<=acauto.cnt;i++)for(j=0;j<ed;j++)ans=max(ans,g[i][j]); printf("Case %d: %d\n",cas,ans); } int main() { // freopen("test.in","r",stdin); int cas=0; crs['A']=0,crs['C']=1,crs['G']=2,crs['T']=3; while(acauto.build())work(++cas); return 0; } /*2896 3065 2243 2825 3341 */
时间: 2024-10-31 22:30:04