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

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

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

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

    Sample Input
    2 2
    A
    B

    Sample Output
    100


    考虑补集转化,我们求出不包含任何一个单词的文本个数,对所有的单词建立AC自动机,在建fail指针的时候延续终止标识符,直接dp即可

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int frd(){
    	int x=0,f=1;char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)    putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=1e2,M=60,Mod=1e4+7;
    struct S1{
    	int trie[N*M+10][26],fail[N*M+10],root,tot;
    	bool End[N*M+10];
    	void insert(char *s){
    		int len=strlen(s),p=root;
    		for (int i=0;i<len;i++){
    			if (!trie[p][s[i]-'A'])	trie[p][s[i]-'A']=++tot;
    			p=trie[p][s[i]-'A'];
    		}
    		End[p]=1;
    	}
    	void make_fail(){
    		static int h[N*M+10];
    		int head=1,tail=0;
    		for (int i=0;i<26;i++)	if (trie[root][i])	h[++tail]=trie[root][i];
    		for (;head<=tail;head++){
    			int Now=h[head];
    			End[Now]|=End[fail[Now]];
    			for (int i=0;i<26;i++){
    				if (trie[Now][i]){
    					int son=trie[Now][i];
    					fail[son]=trie[fail[Now]][i];
    					h[++tail]=son;
    				}else	trie[Now][i]=trie[fail[Now]][i];
    			}
    		}
    	}
    }AC;//Aho-Corasick automaton
    int mlt(int a,int b){
    	int res=1;
    	for (;b;b>>=1,a=1ll*a*a%Mod)	if (b&1)	res=1ll*res*a%Mod;
    	return res;
    }
    int f[N+10][N*M+10];
    int main(){
    	int n=read(),m=read();
    	for (int i=1;i<=n;i++){
    		static char s[N+10];
    		scanf("%s",s);
    		AC.insert(s);
    	}AC.make_fail();
    	f[0][0]=1;
    	for (int i=0;i<m;i++){
    		for (int j=0;j<AC.tot;j++){
    			if (!f[i][j])	continue;
    			for (int k=0;k<26;k++){
    				int son=AC.trie[j][k];
    				if (AC.End[son])	continue;
    				f[i+1][son]=(f[i+1][son]+f[i][j])%Mod;
    			}
    		}
    	}
    	int Ans=mlt(26,m);
    	for (int i=0;i<=AC.tot;i++)	Ans=(Ans-f[m][i])%Mod;
    	printf("%d
    ",(Ans+Mod)%Mod);
    	return 0;
    }
    
  • 相关阅读:
    【codeforces 791D】 Bear and Tree Jumps
    【codeforces 791C】Bear and Different Names
    【codeforces 791B】Bear and Friendship Condition
    【codeforces 791A】Bear and Big Brother
    【t017】YL杯超级篮球赛
    Java Web整合开发(80) -- EJB & WebService
    搜索与排序
    T2821 天使之城 codevs
    T1155 金明的预算方案 codevs
    后缀表达式
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10485816.html
Copyright © 2011-2022 走看看