luogu P4052 [JSOI2007]文本生成器
题目大意
给出n个串,求出长度为m的包含n个串中的至少一个串的串个数
题解
就建好AC自动机之后跑DP就好了
3维表示
当前第几位
在AC自动机上的哪个节点
是否匹配到
code:
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define mod 10007
#define N 6005
#define C 26
using namespace std;
int ch[N][C], nxt[N], vis[N], dp[105][N][2], tot, n, m;
string st;
void insert(){
int len = st.length(), p = 0;
for(int i = 0; i < len; i ++){
if(!ch[p][st[i] - 'A']) ch[p][st[i] - 'A'] = ++ tot;
p = ch[p][st[i] - 'A'];
}
vis[p] = 1;
}
queue<int> q;
void build(){
for(int i = 0; i < C; i ++) if(ch[0][i]) q.push(ch[0][i]);
while(q.size()){
int u = q.front(); q.pop();
for(int i = 0; i < C; i ++){
if(ch[u][i]){
nxt[ch[u][i]] = ch[nxt[u]][i];
vis[ch[u][i]] |= vis[ch[nxt[u]][i]];//继承标记
q.push(ch[u][i]);
} else ch[u][i] = ch[nxt[u]][i];
}
}
}
int main(){
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i = 1; i <= n; i ++) cin >> st, insert();
build();
dp[0][0][0] = 1;
for(int i = 0; i < m; i ++){
for(int j = 0; j <= tot; j ++){
for(int k = 0; k <= 1; k ++){
if(!dp[i][j][k]) continue;
for(int jj = 0; jj < C; jj ++){
int v = ch[j][jj];
dp[i + 1][v][k | vis[v]] += dp[i][j][k];//转移
dp[i + 1][v][k | vis[v]] %= mod;
}
}
}
}
int ret = 0;
for(int i = 0; i <= tot; i ++) ret += dp[m][i][1], ret %= mod;//累加答案
cout << ret;
return 0;
}
zz题
坑点:
大写字母!!!!