Description
给定k个长度不超过L的01串,求有多少长度为n的01串S满足:
1.该串是回文串
2.该串不存在两个不重叠的子串,在给定的k个串中。
即不存在a<=b<c<=d,S[a,b]是k个串中的一个,S[c,d]是k个串中的一个
(It does not contain two non-overlapped substrings in the given list of K binary strings.)
举个例子,若给定2(k=2)个01串:101和1001
1010001和1010101均不满足条件。前者不满足条件1,后者不满足条件2
Input
第一行两个整数n,k
以下k行,每行一个01串
Output
输出一个整数表示答案,答案mod 1000000007(10^9+7)
对原串和反串分别建ac自动机,从两边向中间处理回文串,同时在自动机上走,若匹配到一个串就记录并回到起点
dp状态表示为 当前已确定前缀、后缀在ac自动机上的位置,以及是否已匹配到一个串 的方案数
最后检查是否在跨过中点的位置匹配到一个串
#include<cstdio> #include<cstring> #include<algorithm> const int P=1e9+7; int n,k,ls[33]; char s[33][33]; inline void inc(int&a,int b){ b+=a-P; a=b+(b>>31&P); } struct acam{ int ch[907][2],fa[907]; int S[907][33]; bool e[907]; int ptr; acam(){ memset(this,0,sizeof(acam)); ptr=1; ch[0][0]=ch[0][1]=1; } void ins(char*s,int a){ int w=1; for(int i=0;s[i];++i){ int c=s[i]-'0',&u=ch[w][c]; if(!u)u=++ptr; w=u; S[w][a]|=1<<i; } e[w]=1; } void ins(char*s,int a,int len){ int w=1; for(int i=len-1;i>=0;--i){ int c=s[i]-'0',&u=ch[w][c]; if(!u)u=++ptr; w=u; S[w][a]|=1<<i; } e[w]=1; } void build(){ int q[907],ql=0,qr=0; q[++qr]=1; while(ql!=qr){ int w=q[++ql]; for(int i=0;i<2;++i){ int&u=ch[w][i]; (u?fa[q[++qr]=u]:u)=ch[fa[w]][i]; } } for(int i=2;i<=qr;++i){ int w=q[i],f=fa[w]; e[w]|=e[f]; for(int j=0;j<k;++j)S[w][j]|=S[f][j]; } } }t1,t2; int f[2][907][907][2]; int main(){ scanf("%d%d",&n,&k); for(int i=0;i<k;++i){ scanf("%s",s[i]); ls[i]=strlen(s[i]); t1.ins(s[i],i); t2.ins(s[i],i,ls[i]); } t1.build(); t2.build(); int now=0; f[0][1][1][0]=1; for(int t=0;t<n/2;++t,now^=1){ memset(f[now^1],0,sizeof(f[0][0])*(t1.ptr+2)); for(int c=0;c<2;++c){ for(int a=1;a<=t1.ptr;++a)if(!t1.e[a]){ int a1=t1.ch[a][c],is=0; if(t1.e[a1])a1=1,is=1; int(*f1a)[2]=f[now^1][a1]; int(*f0a)[2]=f[now][a]; for(int b=1;b<=t2.ptr;++b)if(!t2.e[b]){ int b1=t2.ch[b][c]; int v=is; if(t2.e[b1])b1=1,++v; for(int x=0;x+v<2;++x){ inc(f1a[b1][x+v],f0a[b][x]); } } } } } if(n&1){ memset(f[now^1],0,sizeof(f[0][0])*(t1.ptr+2)); for(int c=0;c<2;++c){ for(int a=1;a<=t1.ptr;++a)if(!t1.e[a]){ int a1=t1.ch[a][c],is=0; if(t1.e[a1])a1=1,is=1; int(*f1a)[2]=f[now^1][a1]; int(*f0a)[2]=f[now][a]; for(int b=1;b<=t2.ptr;++b)if(!t2.e[b]){ int v=is; for(int x=0;x+v<2;++x){ inc(f1a[b][x+v],f0a[b][x]); } } } } now^=1; } int ans=0; for(int a=1;a<=t1.ptr;++a){ for(int b=1;b<=t2.ptr;++b){ inc(ans,f[now][a][b][0]); for(int c=0;c<k;++c)if(t1.S[a][c]<<1&t2.S[b][c])goto o; inc(ans,f[now][a][b][1]); o:; } } printf("%d\n",ans); return 0; }