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;
    }
    
  • 相关阅读:
    河南省第十二届大学生程序设计竞赛 F: Information Transmission-1(二分图最大匹配)
    hdu1068:Girls and Boys(最大独立集)
    hdu1068:Girls and Boys(最大独立集)
    hdu1281:棋盘游戏(二分图最大匹配)
    hdu1281:棋盘游戏(二分图最大匹配)
    洛谷P1991 :无线通讯网(最小生成树)
    洛谷P1991 :无线通讯网(最小生成树)
    oGitHub 注册
    Lambda应用设计模式 [转载]
    读取excel数据 到 datagrid 出现 找不到可安装的ISAM
  • 原文地址:https://www.cnblogs.com/kma093/p/12981296.html
Copyright © 2011-2022 走看看