bzoj1030【JSOI2007】文本生成器

1030: [JSOI2007]文本生成器

Time Limit: 1 Sec   Memory Limit: 162 MB
Submit: 2891   Solved: 1193
[ Submit][ Status][ Discuss]

Description

JSOI交給隊員ZYX一個任務,編制一個稱之爲「文本生成器」的電腦軟件:該軟件的使用者是一些低幼人羣,他們現在使用的是GW文本生成器v6版。php

該軟件可以隨機生成一些文章―――老是生成一篇長度固定且全然隨機的文章—— 也就是說,生成的文章中每個字節都是全然隨機的。ios

假設一篇文章中至少包括使用者們瞭解的一個單詞,那麼咱們說這篇文章是可讀的(咱們稱文章a包括單詞b。當且僅當單詞b是文章a的子串)。但是。即便依照這種標準。使用者現在使用的GW文本生成器v6版所生成的文章也是差點兒全然不可讀的。post

ZYX需要指出GW文本生成器 v6生成的所有文本中可讀文本的數量,以即可以成功得到v7更新版。spa

你能幫助他嗎? code

Input

輸入文件的第一行包括兩個正整數。各自是使用者瞭解的單詞總數N (<= 60)。GW文本生成器 v6生成的文本固定長度M;下面N行。每一行包括一個使用者瞭解的單詞。 這裏所有單詞及文本的長度不會超過100。並且僅僅可能包括英文大寫字母A..Z  。 ip

Output

一個整數,表示可能的文章總數。僅僅需要知道結果模10007的值。 get

Sample Input

2 2
A
B

Sample Output

100

HINT

Source




畢竟是本身作的第一道AC本身主動機題,仍是小小地慶祝一下吧……string

咱們若是在Trie樹中表示單詞結尾的節點爲結尾點。it

在加入失配邊後,Trie樹就轉化成一個有向圖,問題也就轉化成:從起點出發,走m步。至少路過一個結尾點的方案數。io

這就可以用動態規劃來實現了。

詳細方法例如如下:

用f[i][j][0]表示走i步到達j點不通過結尾點的方案數,用f[i][j][1]表示走i步到達j點通過結尾點的方案數。

咱們很是easy可以想到狀態轉移方程。

(詳見程序)

終於答案爲∑(i)f[m][i][1]。注意每次計算後都要取模。





#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
#define mod 10007
using namespace std;
int t[6010][26],f[110][6010][2],v[6010],go[6010];
int n,m,tot;
char s[110];
queue<int> q;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void insert()
{
	scanf("%s",s+1);
	int len=strlen(s+1),now=1;
	F(i,1,len)
	{
		int x=s[i]-'A';
		if (!t[now][x]) t[now][x]=++tot;
		now=t[now][x];
	}
	v[now]=1;
}
inline void bfs()
{
	q.push(1);
	while (!q.empty())
	{
		int x=q.front(),y,j;q.pop();v[x]|=v[go[x]];
		F(i,0,25)
		{
			j=go[x];
			while (j&&!t[j][i]) j=go[j];
			if (t[x][i])
			{
				go[y=t[x][i]]=j?t[j][i]:1;
				q.push(y);
			}
			else t[x][i]=j?

t[j][i]:1; } } } inline void dp() { f[0][1][0]=1; F(i,0,m) F(j,1,tot) F(k,0,25) F(l,0,1) { if (v[t[j][k]]) (f[i+1][t[j][k]][1]+=f[i][j][l])%=mod; else (f[i+1][t[j][k]][l]+=f[i][j][l])%=mod; } } int main() { n=read();m=read();tot=1; F(i,1,n) insert(); bfs(); dp(); int ans=0; F(i,1,tot) (ans+=f[m][i][1])%=mod; printf("%d\n",ans); return 0; }

相關文章
相關標籤/搜索