luogu P4052 [JSOI2007]文本生成器

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题

坑点:

大写字母!!!!

posted @ 2019-08-09 14:35  lahlah  阅读(36)  评论(0编辑  收藏  举报