Description
现在有无数个HJA,编号从1一直到无穷。对于编号为 x 的 HJA,我们考虑如何计算他的价值。我们将
Input
第一行是三个正整数
第二行第一个整数 lenl 代表 l 的位数, 接下来
第三行第一个整数 lenr 代表 r 的位数,接下来
接下来 n 行, 每行第一个数代表第
Output
输出答案模 109+7
Sample Input 1
2 10 1
1 1
3 1 0 0
1 1 0
1 0 1
Sample Output 1
97
Sample Input 2
2 10 12
2 5 9
6 6 3 5 4 9 7
2 0 6 1
3 6 7 2 1
Sample Output 2
635439
Sample Input 3
4 2 6
6 1 0 1 1 1 0
6 1 1 0 1 0 0
1 1 2
3 0 1 0 5
4 0 1 1 0 4
3 1 0 1 2
Sample Output 3
2
Solution
该题是一个比较裸的动态规划题,思维难度并不高。考虑
n
个数与一个数的匹配过程,实际上就是字符串问题中的多串匹配问题,所以我们对这
考虑另外一部分,我们要求
Program
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std ;
const int N=210;
const int M=25;
const int K=510;
const int mod=1e9+7;
#define newnode ++tlen
#define inc(a,b) {a+=b; if (a>=mod) a-=mod;}
int f[N][N][K][2];//DP数组
int q[N];
int n,m,k;
int word[N][N],wlen[N];//存储有权单词及其长度
int tlen,root;//trie树的节点个数,trie树根节点编号
int le[N],ri[N],llen,rlen;//左边界和右边界
typedef struct Trie{
int next[M];
int value,fail;
Trie (){
memset (next,0,sizeof(next));
value=fail=0;
}
}T;
T trie[N];
void T_insert (int *s,int l,int v){
int p=root,i;
for (i=1;i<=l;i++){
if (!trie[p].next[s[i]]) trie[p].next[s[i]]=newnode;
p=trie[p].next[s[i]];
}
trie[p].value+=v;
}
void init (){
scanf ("%d %d %d",&n,&m,&k);
int i,j,v;
root=newnode;
scanf ("%d",&llen);
for (i=llen;i>=1;i--) scanf ("%d",&le[i]);
scanf ("%d",&rlen);
for (i=rlen;i>=1;i--) scanf ("%d",&ri[i]);
for (i=1;i<=n;i++){
scanf ("%d ",&wlen[i]);
for (j=wlen[i];j>=1;j--){
scanf ("%d ",&word[i][j]);
}
scanf ("%d",&v);
T_insert(word[i],wlen[i],v);
}
}
void build_ACaotomaton (){
int front=1,tail=1;
int now,i,p;
q[1]=root;
while (front<=tail){
now=q[front++];
for (i=0;i<m;i++){
if (trie[now].next[i]){
p=trie[now].fail;
while (p){
if (trie[p].next[i]){
trie[trie[now].next[i]].fail=trie[p].next[i];
break;
}
p=trie[p].fail;
}
if (!p) trie[trie[now].next[i]].fail=root;
trie[trie[now].next[i]].value+=trie[trie[trie[now].next[i]].fail].value;
q[++tail]=trie[now].next[i];
}
else {
trie[now].next[i]=trie[trie[now].fail].next[i];
if (!trie[now].next[i]) trie[now].next[i]=root;
}
}
}
}
int solve(int *y,int l){
if (!l) return 0;
int ans=0;
int a,b,c,d,e;
int p,data;
for (a=1;a<l;a++)
for (b=1;b<=tlen;b++)
for (c=0;c<=k;c++)
inc(ans,f[a][b][c][0]);
for (a=l;a>=1;a--){
for (b=1;b<=tlen;b++){
for (c=(a==l);c+(a!=1)<=y[a];c++){
p=b;
data=0;
p=trie[p].next[c];
data+=trie[p].value;
for (d=a+1;d<=l;d++){
p=trie[p].next[y[d]];
data+=trie[p].value;
}
for (d=0;d<=k-data;d++){
for (e=0;e<=1;e++) inc(ans,f[a-1][b][d][e]);
}
}
}
}
return ans;
}
int main (){
init ();
build_ACaotomaton ();
n=max (llen,rlen);
f[0][root][0][0]=1;
int a,b,c,d,e,i;
for (a=0;a<n;a++)
for (b=1;b<=tlen;b++)
for (c=0;c<=k;c++)
for (d=0;d<=1;d++)
if (f[a][b][c][d])
for (e=0;e<m;e++)
if (c+trie[trie[b].next[e]].value<=k)
inc(f[a+1][trie[b].next[e]][c+trie[trie[b].next[e]].value][e==0],f[a][b][c][d]);
le[1]--;
for (i=1;i<=llen;i++){
if (le[i]<0) {
le[i]+=m;
le[i+1]--;
}
else break;
}
if (!le[llen]) llen--;
printf("%d\n",(solve(ri,rlen)-solve(le,llen)+mod)%mod);
return 0;
}