题意:
有n个模式串,一个标准串,现在让标准串重组,使得包含最多的模式串,可重叠,问重组后最多包含多少模式串
题解:
显然是AC自动机上的状态压缩DP,不过如果直接开404*500的数组显示开不下,所以这样要将状态hash一下,然后再DP,因为这个字母加起来为40,所以状态数不超过15000,所以可以接受。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 using namespace std; 4 5 const int AC_N=100*11,tyn=4;//数量乘串长,类型数 6 struct AC_automation{ 7 int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot; 8 inline int getid(char x){ 9 if(x=='A')return 0; 10 if(x=='C')return 1; 11 if(x=='G')return 2; 12 return 3; 13 } 14 void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));} 15 void init(){tot=-1,fail[0]=-1,nw();} 16 void insert(char *s,int x=0){ 17 for(int len=strlen(s),i=0,w;i<len;x=tr[x][w],i++) 18 if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot; 19 cnt[x]++;//串尾标记 20 } 21 void build(int head=1,int tail=0){ 22 for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i]; 23 while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++) 24 if(tr[x][i])fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i],cnt[tr[x][i]]+=cnt[tr[fail[x]][i]]; 25 else tr[x][i]=tr[fail[x]][i]; 26 } 27 28 }AC; 29 30 inline void up(int &a,int b){if(a<b)a=b;} 31 32 char s[100]; 33 int n,len,cnt,ic=0,na,nc,ng,nt; 34 int hsh[41][41][41][41],dp[15000][501]; 35 36 void fuck() 37 { 38 int ed=0,ans=0; 39 na=nc=ng=nt=0; 40 for(int i=0;s[i]!='