[bzoj1030] [JSOI2007]文本生成器
阿新 • • 發佈:2019-02-10
tom 文件 大寫字母 std urn str write 枚舉 包含
表示長度為\(i\)的串,最後一位在自動機上的第\(j\)個點,然後枚舉狀態 ,轉移給兒子就好了。
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
Solution
\(AC\)自動機上\(dp\)。
正難則反,考慮統計不合法的字串。
先建出\(AC\)自動機,然後這題其實就和bzoj1009: [HNOI2008]GT考試差不多了。
設\(f[i][j]\)
#include<bits/stdc++.h> using namespace std; void read(int &x) { x=0;int f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; } #define write(x) printf("%d\n",x) const int maxn = 2e4+10; const int mod = 10007; int n,m,f[102][maxn]; char c[maxn]; int qpow(int a,int x) { int res=1; for(;x;x>>=1,a=1ll*a*a%mod) if(x&1) res=1ll*res*a%mod; return res; } struct AC_automaton { int son[maxn][26],fail[maxn],tot,vis[maxn]; void ins(char *s) { int len=strlen(s+1),now=0; for(int i=1,t;i<=len;i++) { if(!son[now][t=s[i]-'A']) son[now][t]=++tot; now=son[now][t]; }vis[now]=1; } void build() { queue<int > q;for(int i=0;i<26;i++) if(son[0][i]) q.push(son[0][i]); while(!q.empty()) { int now=q.front();q.pop(); for(int i=0;i<26;i++) if(son[now][i]) fail[son[now][i]]=son[fail[now]][i],q.push(son[now][i]); else son[now][i]=son[fail[now]][i]; if(vis[fail[now]]) vis[now]=1; } } void solve() { f[0][0]=1; for(int i=0;i<m;i++) for(int j=0;j<=tot;j++) { if(vis[j]||!f[i][j]) continue; for(int k=0;k<26;k++) f[i+1][son[j][k]]=(f[i+1][son[j][k]]+f[i][j])%mod; } int ans=0; for(int i=0;i<=tot;i++) if(!vis[i]) ans=(ans+f[m][i])%mod; write((qpow(26,m)-ans+mod)%mod); } }AC; int main() { read(n),read(m); for(int i=1;i<=n;i++) scanf("%s",c+1),AC.ins(c); AC.build(),AC.solve(); return 0; }
[bzoj1030] [JSOI2007]文本生成器