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;
}