数位DP
匹配要用AC自动机,转移的时候要记录一下当前在哪个节点上。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int P=1e9+7;
int n,m,li,tot,x,y;
int l[210],r[210],v[210],fail[210],son[210][25],nxt[210][25];
int f[5][210][510][5][5];
inline void add(int &x,int y){
if((x+=y)>=P) x-=P;
}
inline int calc(int *a){
memset(f,0,sizeof(f));
f[0][0][0][1][1]=1; int S=0;
for(int i=0;i<*a;i++,S^=1){
for(int j=0;j<=tot;j++)
for(int k=0;k<=li;k++)
for(int s=0;s<=1;s++)
for(int w=0;w<=1;w++)
f[S^1][j][k][s][w]=0;
for(int j=0;j<=tot;j++)
for(int k=0;k<=li;k++)
for(int s=0;s<=1;s++)
for(int w=0;w<=1;w++){
if(!f[S][j][k][s][w]) continue;
if(s){
for(int t=0;t<a[i+1];t++){
if(w && !t){
add(f[S^1][0][0][0][1],f[S][j][k][s][w]);
continue;
}
if(k+v[nxt[j][t]]>li) continue;
add(f[S^1][nxt[j][t]][k+v[nxt[j][t]]][0][0],f[S][j][k][s][w]);
}
if(w && !a[i+1]){
add(f[S^1][0][0][0][1],f[S][j][k][s][w]);
continue;
}
if(k+v[nxt[j][a[i+1]]]>li) continue;
add(f[S^1][nxt[j][a[i+1]]][k+v[nxt[j][a[i+1]]]][1][0],f[S][j][k][s][w]);
}
else{
for(int t=0;t<m;t++){
if(w && !t){
add(f[S^1][0][0][0][1],f[S][j][k][s][w]);
continue;
}
if(k+v[nxt[j][t]]>li) continue;
add(f[S^1][nxt[j][t]][k+v[nxt[j][t]]][0][0],f[S][j][k][s][w]);
}
}
}
}
int ret=0;
for(int i=0;i<=tot;i++)
for(int j=0;j<=li;j++)
for(int k=0;k<=1;k++)
for(int s=0;s<=1;s++)
add(ret,f[S][i][j][k][s]);
return ret;
}
queue<int> Q;
void Build(){
Q.push(0);
while(!Q.empty()){
int x=Q.front(); Q.pop();
for(int i=0;i<m;i++)
if(son[x][i]){
int u=son[x][i],p=fail[x];
if(x==0) fail[u]=0;
else{
while(!son[p][i] && p) p=fail[p];
fail[u]=son[p][i];
}
v[u]+=v[fail[u]];
Q.push(u);
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&li);
scanf("%d",l); for(int i=1;i<=*l;i++) scanf("%d",l+i);
scanf("%d",r); for(int i=1;i<=*r;i++) scanf("%d",r+i);
for(int i=1;i<=n;i++){
scanf("%d",&x);
int cur=0;
while(x--){
scanf("%d",&y);
if(son[cur][y]) cur=son[cur][y];
else cur=son[cur][y]=++tot;
}
scanf("%d",&y);
v[cur]+=y;
}
l[*l]--;
for(int i=*l;i;i--)
if(l[i]<0) l[i]+=m,l[i-1]--;
Build();
for(int i=0;i<=tot;i++)
for(int j=0;j<m;j++){
if(son[i][j]) nxt[i][j]=son[i][j];
else{
int p=fail[i];
while(!son[p][j] && p) p=fail[p];
nxt[i][j]=son[p][j];
}
}
//calc(r);
//cout<<calc(r)<<' '<<calc(l)<<endl;
printf("%d\n",(calc(r)+P-calc(l))%P);
return 0;
}