/*************************
麻婆豆腐
AC自动机 + 数位dp
好题!
每个字符串都有一个权值,如果一个数字串中出现该串那么
该数字串就的权值就加上字符串的权值,
求区间内数字串权值小于等于给定值的数量。
AC自动机状态转移,数位dp枚举每一位。
再统计符合条件状态数。
**********************/
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
#define maxn 500010
struct Trie{
int next[maxn][26],fail[maxn];
int end[maxn];
int root,L;
int newNode(){
for(int i=0;i<26;i++) next[L][i] = -1;
end[L++] = 0;
return L-1;
}
void init(){
L = 0;
root = newNode();
}
void insert(int str[],int len,int val){
//printf("insert:%s\n",str);
int now = root;
for(int i=0;i<len;i++){
int temp = str[i];
if(next[now][temp] == -1){
next[now][temp] = newNode();
}
now = next[now][temp];
}
end[now] += val;
}
void build(){
queue<int> que;
fail[root] = root;
for(int i=0;i<26;i++){
if( next[root][i] == -1){
next[root][i] = root;
}else{
fail[next[root][i]] = root;
que.push(next[root][i]);
}
}
while(!que.empty()){
int now = que.front();
que.pop();
end[now] += end[fail[now]];
for(int i=0;i<26;i++){
int t = next[now][i];
if(t==-1){
next[now][i] = next[fail[now]][i];
}else{
fail[t] = next[fail[now]][i];
//printf("id:%d fail:%d\n",t,fail[t]);
que.push(t);
}
}
}
}
void debug(){
for(int i=0;i<L;i++){
printf("id:%3d fail:%3d end:%3d next:[",i,fail[i],end[i]);
for(int j=0;j<26;j++){
printf(" %2d",next[i][j]);
}
printf("]\n");
}
}
}ac;
typedef long long LL;
const int mod = 1000000007;
int n,m,k;
int len[2];
int p[2][250];
int bit[250];
int buf[250];
LL dp[210][420][520];
LL dfs(int h,int s,int now,bool flag, bool zero){
now -= ac.end[s];
if(now < 0) return 0;
if(h==-1) {
//cout << sum << " " << now << endl;
return 1;
}
if(!flag && dp[h][s][now] != -1) return dp[h][s][now];
LL res = 0;
if(zero){
res += dfs(h-1,s,now,flag && bit[h]==0,true);
res %= mod;
}else{
res += dfs(h-1,ac.next[s][0],now,flag && bit[h]==0,false);
res %= mod;
}
int up = flag?bit[h]:m-1;
for(int i=1;i<=up;i++){
res += dfs(h-1,ac.next[s][i],now,flag && i==up,false);
res %= mod;
}
if(!flag && !zero) dp[h][s][now] = res;
return res;
}
LL solve(){
for(int i=0;i<len[0];i++) bit[i] = p[0][i];
//for(int i=0;i<len[0];i++) cout << bit[i];
//cout << endl;
LL ans = -dfs(len[0]-1,0,k,true,true);
//cout << ans << endl;
for(int i=0;i<len[1];i++) bit[i] = p[1][i];
//for(int i=0;i<len[1];i++) cout << bit[i];
//cout << endl;
memset(dp,-1,sizeof(dp));
ans += dfs(len[1]-1,0,k,true,true);
ans = (ans%mod + mod)%mod;
return ans;
}
int main(){
while(cin >> n >> m >> k){
scanf("%d",&len[0]);
for(int i=0;i<len[0];i++) scanf("%d",&p[0][len[0] - i - 1]);
// l-1
for(int i=0;i<len[0];i++){
if(p[0][i] == 0) p[0][i] = m-1;
else{
p[0][i]--;
break;
}
}
scanf("%d",&len[1]);
for(int i=0;i<len[1];i++) scanf("%d",&p[1][len[1] - i - 1]);
ac.init();
memset(dp,-1,sizeof(dp));
int t,temp,v;
while(n--){
scanf("%d",&t);
for(int i=0;i<t;i++) scanf("%d",&buf[i]);
scanf("%d",&v);
ac.insert(buf,t,v);
}
ac.build();
//ac.debug();
cout << solve() << endl;
}
return 0;
}
Codeforces 433E
最新推荐文章于 2023-06-07 15:53:39 发布