显然是AC自动机dp。
小的直接dp大的矩阵乘法。
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=200+10,mo=1000000007;
char a[maxn][maxn],b[maxn][maxn];
int l1[maxn],l2[maxn];
int g[maxn][26],fail[maxn],next[maxn][26],trans[maxn][maxn],f[maxn][maxn],dl[maxn],dy[maxn],sta[80];
int o[maxn][maxn],an[maxn][maxn],dis[maxn][maxn],wd[maxn][maxn];
bool bz[maxn];
int i,j,k,l,t,n,m,len,tot,top,head,tail,root,last,now,ans;
int insert(int x,int c){
if (!g[x][c]) g[x][c]=++tot;
return g[x][c];
}
void work(){
fo(i,1,tot)
fo(j,1,n)
if (trans[i][j]!=-1){
t=trans[i][j];
if (l1[j]==1){
//dis[i][t]++;
dis[i+tot][t+tot]++;
}
else dis[i][t+tot]++;
}
fo(i,1,tot) dis[i+tot][i]++;
wd[1][tot+1]=1;
while (len){
sta[++top]=len%2;
len/=2;
}
fo(i,1,2*tot) an[i][i]=1;
while (top){
fo(i,1,2*tot)
fo(j,1,2*tot)
o[i][j]=0;
fo(k,1,2*tot)
fo(i,1,2*tot)
fo(j,1,2*tot)
o[i][j]=(o[i][j]+(ll)an[i][k]*an[k][j]%mo)%mo;
fo(i,1,2*tot)
fo(j,1,2*tot)
an[i][j]=o[i][j];
if (sta[top]){
fo(i,1,2*tot)
fo(j,1,2*tot)
o[i][j]=0;
fo(k,1,2*tot)
fo(i,1,2*tot)
fo(j,1,2*tot)
o[i][j]=(o[i][j]+(ll)an[i][k]*dis[k][j]%mo)%mo;
fo(i,1,2*tot)
fo(j,1,2*tot)
an[i][j]=o[i][j];
}
top--;
}
fo(i,1,2*tot)
fo(j,1,2*tot)
o[i][j]=0;
fo(k,1,2*tot)
fo(i,1,2*tot)
fo(j,1,2*tot)
o[i][j]=(o[i][j]+(ll)wd[i][k]*an[k][j]%mo)%mo;
fo(i,1,2*tot)
fo(j,1,2*tot)
an[i][j]=o[i][j];
fo(j,tot+1,2*tot) ans=(ans+an[1][j])%mo;
printf("%d\n",ans);
}
int main(){
freopen("sorcery.in","r",stdin);freopen("sorcery.out","w",stdout);
scanf("%d%d%d",&n,&m,&len);
fo(i,1,n)
scanf("%s",a[i]+1),l1[i]=strlen(a[i]+1);
fo(i,1,m)
scanf("%s",b[i]+1),l2[i]=strlen(b[i]+1);
tot=root=1;
fo(i,1,m){
last=1;
fo(j,1,l2[i]) last=insert(last,b[i][j]-'a');
dy[i]=last;
bz[last]=1;
}
fo(i,0,25)
if (g[1][i]) next[1][i]=g[1][i];else next[1][i]=1;
fo(i,0,25)
if (g[1][i]){
dl[++tail]=g[1][i];
fail[g[1][i]]=1;
j=g[1][i];
fo(k,0,25)
if (g[j][k]) next[j][k]=g[j][k];else next[j][k]=next[1][k];
}
while (head
now=dl[++head];
bz[now]|=bz[fail[now]];
fo(i,0,25)
if (g[now][i]){
j=fail[now];
while (j>1&&!g[j][i]) j=fail[j];
if (g[j][i]) j=g[j][i];
fail[g[now][i]]=j;
j=g[now][i];
fo(k,0,25)
if (g[j][k]) next[j][k]=g[j][k];else next[j][k]=next[fail[j]][k];
dl[++tail]=g[now][i];
}
}
fo(i,1,tot){
if (bz[i]) continue;
fo(j,1,n){
last=i;
fo(k,1,l1[j]+1){
if (k>l1[j]) break;
last=next[last][a[j][k]-'a'];
if (bz[last]) break;
}
if (k<=l1[j]) trans[i][j]=-1;else trans[i][j]=last;
}
}
if (len>100){
work();
return 0;
}
f[0][1]=1;
fo(i,0,len-1)
fo(j,1,tot)
if (f[i][j])
fo(k,1,n)
if (i+l1[k]<=len&&trans[j][k]!=-1) (f[i+l1[k]][trans[j][k]]+=f[i][j])%=mo;
fo(j,1,tot) (ans+=f[len][j])%=mo;
printf("%d\n",ans);
}