分析:
巨恶心的一题双代码题。
对于前半部分,把禁止出现的字符串建一颗AC自动机。
然后枚举每个位置用了某个模板串后转移到哪里。
然后直接DP即可。
但是对于后半部分数据,则必须写一个矩阵加速。。。
因为模板串长度不超过2,只需要对所有长度为2的建一个虚拟节点就行了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define SF scanf
#define PF printf
#define MAXN 310
#define MOD 1000000007
using namespace std;
typedef long long ll;
char s[MAXN][MAXN];
char s1[MAXN][MAXN];
int n,m,l,tot;
ll c[MAXN][MAXN];
int maxS;
struct matrix{
ll a[MAXN][MAXN];
void operator *=(const matrix &x) {
memset(c,0,sizeof c);
for(int i=0;i<maxS;i++)
for(int j=0;j<maxS;j++)
for(int k=0;k<maxS;k++)
c[i][j]=(c[i][j]+a[i][k]*x.a[k][j]%MOD)%MOD;
for(int i=0;i<maxS;i++)
for(int j=0;j<maxS;j++)
a[i][j]=c[i][j];
}
}T,e,res;
struct node{
int flag;
node *fail;
node *ch[26];
}Tree[MAXN];
node *ncnt=Tree,*rt=Tree;
int tr[MAXN][MAXN];
int len[MAXN];
void ins(node *now,char *c){
if(*c==0){
now->flag=1;
return ;
}
int d=*c-'a';
if(now->ch[d]==NULL)
now->ch[d]=++ncnt;
ins(now->ch[d],++c);
}
queue<node*> q;
void build(){
q.push(rt);
rt->fail=rt;
while(!q.empty()){
node *now=q.front();
q.pop();
for(int i=0;i<26;i++){
node *x=now;
if(x->ch[i]==NULL){
if(x==rt)
x->ch[i]=rt;
else
x->ch[i]=x->fail->ch[i];
continue;
}
q.push(x->ch[i]);
if(now==rt){
x->ch[i]->fail=rt;
continue;
}
x=x->fail;
while(x!=rt&&x->ch[i]==NULL)
x=x->fail;
if(x->ch[i]!=NULL)
now->ch[i]->fail=x->ch[i];
else
now->ch[i]->fail=rt;
}
now->flag|=now->fail->flag;
}
}
matrix fsp(matrix &x,int t){
for(int i=0;i<tot*2;i++)
e.a[i][i]=1;
while(t){
if(t&1)
e*=x;
x*=x;
t>>=1;
}
return e;
}
int dp[MAXN][MAXN];
int main(){
SF("%d%d%d",&m,&n,&l);
for(int i=1;i<=m;i++){
SF("%s",s1[i]);
len[i]=strlen(s1[i]);
}
for(int i=1;i<=n;i++){
SF("%s",s[i]);
ins(rt,s[i]);
}
build();
tot=ncnt-rt+1;
for(int i=0;i<tot;i++)
for(int j=1;j<=m;j++){
node *x=rt+i;
if(x->flag)
tr[i][j]=-1;
else{
for(int k=0;k<len[j]&&x->flag==0;k++)
x=x->ch[s1[j][k]-'a'];
if(x->flag)
tr[i][j]=-1;
else
tr[i][j]=x-rt;
}
}
if(l<=100){
dp[0][0]=1;
for(int i=0;i<l;i++)
for(int now=0;now<tot;now++)
for(int j=1;j<=m;j++)
if(tr[now][j]!=-1&&i+len[j]<=l)
(dp[i+len[j]][tr[now][j]]+=dp[i][now])%=MOD;
int ans=0;
for(int now=0;now<tot;now++)
ans=(ans+dp[l][now])%MOD;
PF("%d",ans);
}
else{
maxS=tot*2;
for(int i=0;i<tot;i++)
for(int j=1;j<=m;j++){
if(tr[i][j]==-1)
continue;
if(len[j]==1)
T.a[i+tot][tr[i][j]+tot]++;
else
T.a[i][tr[i][j]+tot]++;
}
for(int i=0;i<tot;i++)
T.a[i+tot][i]++;
res.a[0][tot]=1;
res*=fsp(T,l);
int ans=0;
for(int i=tot;i<=2*tot;i++)
ans=(ans+res.a[0][i])%MOD;
PF("%d\n",ans);
}
}