zoukankan      html  css  js  c++  java
  • [JSOI2007]文本生成器

    传送门

    Analysis

    AC自动机+dp
    直接从正面做
    (f[i][j][0/1])表示在节点(i),串长为(j),是否已经经过结尾点的总方案数,然后从父亲向儿子转移
    (dp)的时候不用跳(fail),在构建(fail)指针的时候顺带把对于结尾点的标记通过(fail)指针扩展到它在(fail)树上的祖先(不知道这样理解对不对)

    ps:大写看成小写调了1h……

    放代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 10000 + 10;
    const int mod = 10007;
    char s[N];
    int n, m, ch[N][30], lst[N], fail[N], val[N], f[N][105][2], sz = 1, ans;
    void insert(char *s) {
    	int u = 0; int n = strlen(s);
    	for (register int i = 0; i < n; ++i) {
    		int c = s[i] - 'A';
    		if (!ch[u][c]) {
    			memset(ch[sz], 0, sizeof ch[sz]);
    			val[sz] = 0;
    			ch[u][c] = sz++;
    //			cout << u << " " << c << ' ' << ch[u][c] << endl;
    		} u = ch[u][c];
    	} val[u] = 1;
    }
    void getfail() {
    	queue <int> q;
    	int u = 0; fail[0] = 0;
    	for (register int i = 0; i < 26; ++i) 
    		if (ch[0][i]) q.push(ch[0][i]), fail[ch[0][i]] = lst[ch[0][i]] = 0;
    	while (!q.empty()) {
    		int r = q.front(); q.pop();
    		for (register int i = 0; i < 26; ++i) {
    			u = ch[r][i];
    			if (!ch[r][i]) {
    				ch[r][i] = ch[fail[r]][i];
    				continue;
    			} q.push(u);
    			int v = fail[r];
    			while (v && !ch[v][i]) v = fail[v];
    			fail[u] = ch[v][i];
    			val[u] |= val[fail[u]];
    			lst[u] = val[fail[u]] ? fail[u] : lst[fail[u]]; 
    		}
    	}
    }
    void dp() {
    	f[0][0][0] = 1;
    	for (register int i = 1; i <= m; ++i) 
    		for (register int j = 0; j < sz; ++j) 
    			for (register int k = 0; k < 26; ++k) {
    				int u = ch[j][k];
    //				cout << u << ' ' << i << ' ' << j << endl;
    				if (val[u]) f[u][i][1] = (f[u][i][1] + f[j][i - 1][0] + f[j][i - 1][1]) % mod;
    				else {
    					f[u][i][0] = (f[u][i][0] + f[j][i - 1][0]) % mod;
    					f[u][i][1] = (f[u][i][1] + f[j][i - 1][1]) % mod;
    				}
    			}
    }
    int main() {
    	cin >> n >> m;
    	for (register int i = 1; i <= n; ++i) {scanf("%s", s); insert(s);}
    	getfail(); 
    	dp();
    	for (register int i = 0; i < sz; ++i) ans = (ans + f[i][m][1]) % mod;
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    树莓派成长日记03
    一些特殊文字的过滤Private Use Area:E000F8FF
    MongoDb 相关
    SQL 相关技术点收集贴
    正则表达式提取文本的日期
    MVC 相关技术点收集贴
    使用 json2.js注意点
    C#画图 GDI+
    PHP模拟POST,验证页面的返回状态
    EF-Entity Framework 相关技术点收集贴
  • 原文地址:https://www.cnblogs.com/kma093/p/12981296.html
Copyright © 2011-2022 走看看