列表

详情


NC234268. 文本生成器加强版

描述

JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群, 他们现在使用的是GW文本生成器v6版。
该软件可以随机生成一些文章―――总是生成一篇长度固定且完全随机的文 章—— 也就是说,生成的文章中每个字节都是完全随机的。
如果一篇文章中至少包含使用者们了解的一个单词, 那么我们说这篇文章是可读的(我们称文章a包含单词b,当且仅当单词b是文章a的子串)。
但是,即使按照这样的标准,使用者现在使用的GW文本生成器v6版所生成的文章也是几乎完全不可读的?
ZYX需要指出GW文本生成器 v6 生成的所有文本中可读文本的数量,以便能够成功获得v7更新版。你能帮助他吗?

输入描述

输入文件的第一行包含两个正整数,分别是使用者了解的单词总数N ( ≤ 60),GW文本生成器 v6生成的文本固 定长度M;
以下N行,每一行包含一个使用者了解的单词。这里所有单词及文本的长度不会超过100,并且只可能包含英文大写字母A..Z

输出描述

一个整数,表示可能的文章总数。只需要知道结果模10007的值。

示例1

输入:

2 2
A
B

输出:

100

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 2897ms, 内存消耗: 238312K, 提交时间: 2022-08-05 22:53:50

#include<bits/stdc++.h>
using namespace std;
#define fastio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int N=8005,M=10007;
int t[N][26],cnt,isword[N],fail[N];
void insert(string s){
    int x=0;
    for(auto& i:s){
        int k=i-'A';
        if(!t[x][k])t[x][k]=++cnt;
        x=t[x][k];
    }
    isword[x]=1;
}
void build(){
    queue<int>q;
    rep(i,0,25)if(t[0][i])q.push(t[0][i]);
    while(!q.empty()){
        int k=q.front();q.pop();
        rep(i,0,25){
            int & son=t[k][i];
            if(son)q.push(son),fail[son]=t[fail[k]][i];
            else son=t[fail[k]][i];
        }
    }
}
int ok[N];
void generate(){
    memset(ok,1,sizeof(ok));
    rep(i,1,cnt){
        for(int j=i;j;j=fail[j])if(isword[j])ok[i]=0;
    }
}
int dp[10010][6060];
int main(){
    fastio;
    int n,m;cin>>n>>m;
    rep(i,1,n){
        string s;cin>>s;insert(s);
    }
    build();generate();
    dp[0][0]=1;
    rep(i,0,m)rep(j,0,cnt)rep(k,0,25){
        int son=t[j][k];
        if(!ok[son])continue;
        (dp[i+1][son]+=dp[i][j])%=M;
    }
    int ans=0,ans2=1;
    rep(j,0,cnt)(ans+=dp[m][j])%=M;
    rep(i,1,m)(ans2*=26)%=M;
    cout<<(ans2-ans+M)%M<<endl;
}

C++(clang++ 11.0.1) 解法, 执行用时: 4054ms, 内存消耗: 274816K, 提交时间: 2023-05-13 19:52:33

#include<bits/stdc++.h>
using namespace std;
const int N=10007;
int n,m,t[N][27],cnt,ne[N],tag[N],tot,tt[N],sum=1,f[11111][N],ans;
string s;
void add(){
	int p=0,len=s.size();
	for(int i=0;i<len;i++){
		int j=s[i]-'A';
		if(!t[p][j])t[p][j]=++cnt;
		p=t[p][j];
	}
	tag[p]=1;
}
void kmp(){
	queue<int>q;
	for(int i=0;i<26;i++)if(t[0][i])q.push(t[0][i]);
	while(!q.empty()){
		int p=q.front();
		q.pop();
		tt[++tot]=p;
		for(int i=0;i<26;i++){
			int j=t[p][i],v=t[ne[p]][i];
			if(j){
				ne[j]=v;
				q.push(j);
				tag[j]|=tag[v];
			}
			else t[p][i]=v;
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>s;
		add();
	}
	kmp();
	f[0][0]=1;
	for(int i=1;i<=m;i++){
		sum=sum*26%N;
		for(int j=0;j<=tot;j++){
			for(int v=0;v<26;v++){
				int k=t[tt[j]][v];
				if(!tag[k])f[i][k]=(f[i][k]+f[i-1][tt[j]])%N;
			}
		}
	}
	for(int i=0;i<=cnt;i++)ans=(ans+f[m][i])%N;
	cout<<(sum+N-ans)%N;
}

上一题