当时
显然的自动机上就完了
当时直接显然是不行的
但是发现基本串长度不大于二
考虑矩乘优化
表示有几个基本串使得在自动机上走到
如果所有串长相同就可以直接快速幂了
但是串长有有
不同长度不好处理拼起来的情况
设表示长度为1的串的转移矩阵
为长度为2的
考虑构造矩阵
这样的转移矩阵就可以了
#include<bits/stdc++.h>
using namespace std;
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
int n,m,l;
const int N=55,M=105;
const int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?a-=mod:a;}
inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
inline int dec(int a,int b){return (a-=b)<0?a+=mod:a;}
inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));return res;
}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
namespace Ac{
int nxt[M][26],tot,fail[M],ed[M];
inline void insert(char *s){
int p=0;
for(int i=1,len=strlen(s+1);i<=len;i++){
int c=s[i]-'a';
if(!nxt[p][c])nxt[p][c]=++tot;
p=nxt[p][c];
}
ed[p]++;
}
queue<int> q;
inline void build(){
for(int i=0;i<26;i++){
if(nxt[0][i])fail[nxt[0][i]]=0,q.push(nxt[0][i]);
}
while(!q.empty()){
int p=q.front();q.pop();
for(int c=0;c<26;c++){
int v=nxt[p][c];
if(!v)nxt[p][c]=nxt[fail[p]][c];
else fail[v]=nxt[fail[p]][c],q.push(v);
}
ed[p]+=ed[fail[p]];
}
}
inline int go(int p,char *s){
if(ed[p])return -1;
for(int i=1,len=strlen(s+1);i<=len;i++){
int c=s[i]-'a';
p=nxt[p][c];
if(ed[p])return -1;
}
return p;
}
}
using namespace Ac;
char s[N][M],t[N][M];
int len[N];
namespace solve1{
int f[M][M];
inline void main(){
f[0][0]=1;
for(int i=0;i<l;i++)
for(int j=0;j<=tot;j++)
for(int k=1;k<=n;k++)
if(i+len[k]<=l){
int p=go(j,s[k]);
if(p!=-1)
Add(f[i+len[k]][p],f[i][j]);
}
int res=0;
for(int i=0;i<=tot;i++)Add(res,f[l][i]);
cout<<res<<'
';
}
}
namespace solve2{
int lim;
struct mat{
int a[M*2][M*2];
mat(){memset(a,0,sizeof(a));}
friend inline mat operator *(const mat &a,const mat &b){
mat c=mat();
for(int i=0;i<=lim;i++)
for(int k=0;k<=lim;k++)
for(int j=0;j<=lim;j++)
Add(c.a[i][j],mul(a.a[i][k],b.a[k][j]));
return c;
}
}ret,ans;
inline mat ksm(mat a,int b,mat res){
for(;b;b>>=1,a=a*a)if(b&1)res=res*a;
return res;
}
inline void main(){
lim=tot*2+1;
for(int i=0;i<=tot;i++)ret.a[i+tot+1][i]=1;
for(int i=0;i<=tot;i++)
for(int j=1;j<=n;j++){
if(len[j]==2){
int p=go(i,s[j]);
if(p!=-1)ret.a[i][p+tot+1]++;
}
}
for(int i=0;i<=tot;i++)
for(int j=1;j<=n;j++){
if(len[j]==1){
int p=go(i,s[j]);
if(p!=-1)ret.a[i+tot+1][p+tot+1]++;
}
}
ret=ksm(ret,l-1,ret);
ans.a[0][tot+1]=1;
ans=ans*ret;
int res=0;
for(int i=0;i<=tot;i++)
Add(res,ans.a[0][i+tot+1]);
cout<<res;
}
}
int main(){
n=read(),m=read(),l=read();
for(int i=1;i<=n;i++)scanf("%s",s[i]+1),len[i]=strlen(s[i]+1);;
for(int i=1;i<=m;i++)scanf("%s",t[i]+1),insert(t[i]);
build();
if(l<=100)solve1::main();
else solve2::main();
}