• [JSOI2007]文本生成器


    容斥原理, 求出所有的情况减去不可读的情况就是可读的文本数了a
    找不可读文本的数量类似于病毒那一题趴我觉得
    DP转移的话...
    用f[i][j] 表示当前在节点j, 且串长为i时的情况

    #include <bits/stdc++.h>
    using namespace std;
    const int MOD = 1e4 + 7;
    const int N = 20005;
    
    int n, m, cnt;
    int f[N][10000];//f[i][j] : 当前在节点j, 且串长为i时的情况
    struct {
    	int vis[26];
    	int fail;
    	int end;
    } AC[N];
    
    void build(string s) {
    	int now = 0;
    	for(int i = 0; i < s.size(); i++) {
    		if(!AC[now].vis[s[i] - 'A']) 
    			AC[now].vis[s[i] - 'A'] = ++cnt;
    		now = AC[now].vis[s[i] - 'A'];
    	}
    	AC[now].end = 1;
    }
    void Get_fail() {
    	queue<int> q;
    	for(int i = 0; i < 26; i++) 
    		if(AC[0].vis[i]) {
    			AC[AC[0].vis[i]].fail = 0;
    			q.push(AC[0].vis[i]);
    		}
    	while(!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = 0; i < 26; i++) {
    			if(AC[u].vis[i]) {
    				AC[AC[u].vis[i]].fail = AC[AC[u].fail].vis[i];
    				AC[AC[u].vis[i]].end |= AC[AC[AC[u].vis[i]].fail].end;
    				q.push(AC[u].vis[i]);
    			}
    			else AC[u].vis[i] = AC[AC[u].fail].vis[i];
    		}
    	}
    }
    int main() {
    	ios :: sync_with_stdio(0);
    
    	string s;
    	cin >> n >> m;
    	for(int i = 1; i <= n; i++)
    		cin >> s, build(s);
    	Get_fail();	
    	f[0][0] = 1;
    	for(int i = 1; i <= m; i++) 
    		for(int j = 0; j <= cnt; j++) 
    			for(int k = 0; k < 26; k++) 
    				if(!AC[AC[j].vis[k]].end)
    					(f[i][AC[j].vis[k]] += f[i - 1][j] ) %= MOD;
    	int ans = 0;
    	for(int i = 0; i <= cnt; i++)
    		(ans += f[m][i] ) %= MOD;
    	int sum = 26;
    	for(int i = 1; i < m; i++)
    		(sum *= 26) %= MOD;
    	cout << (sum - ans + MOD) % MOD;
    	return 0;
    }
    
  • 相关阅读:
    Linux 修改 root密码
    python实现 CI/CD(jenkins+gitlab)
    redis集群
    土木工程材料0732
    C语言程序设计【1032】
    汽车文化【1196】
    应用写作0045
    思想道德修养与法律基础[1053]
    英语【0002】
    社区管理【0272】
  • 原文地址:https://www.cnblogs.com/hyxss/p/13883341.html
Copyright © 2020-2023  润新知