题意:给若干种个串,再给个主串,然后把主串打乱顺序,使得包含子串尽量多(一种可以有多个,两个之间可以部分重叠)。如第一组数据,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 */