標籤:pen scanf clu pac sub 更新 insert nbsp can
1030: [JSOI2007]文本產生器Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 4859 Solved: 2019
[Submit][Status][Discuss]Description
JSOI交給隊員ZGX一個任務,編製一個稱之為“文本產生器”的電腦軟體:該軟體的使用者是一些戰艦狗,
他們現在使用的是GW文本產生器v6版。該軟體可以隨機產生一些文章―――總是產生一篇長度固定且完全隨機的文
章—— 也就是說,產生的文章中每個位元組都是完全隨機的。如果一篇文章中至少包含使用者們瞭解的一個單詞,
那麼我們說這篇文章是可讀的(我們稱文章a包含單詞b,若且唯若單詞b是文章a的子串)。但是,即使按照這樣的
標準,使用者現在使用的GW文本產生器v6版所產生的文章也是幾乎完全不可讀的?。ZGX需要指出GW文本產生器 v6
產生的所有文本中可讀文本的數量,以便能夠成功獲得v7更新版。你能協助他嗎?
Input
輸入檔案的第一行包含兩個正整數,分別是使用者瞭解的單詞總數N (<= 60),GW文本產生器 v6產生的文本固
定長度M;以下N行,每一行包含一個使用者瞭解的單詞。這裡所有單詞及文本的長度不會超過100,並且只可能包
含英文大寫字母A..Z
Output
一個整數,表示可能的文章總數。只需要知道結果模10007的值。
Sample Input2 2
A
BSample Output100思路{ AC自動機裸題。 然而對於我這種一道AC自動機都沒刷過的 只會匹配的辣雞來說還是比較難的。 肯定想到是DP,怎麼設狀態! 我們應當明確求神馬。直接求方案數不行。 那也可以總情況數減去不行的方案數。 我們想,一個目標串列的話最多走到AC自動機末尾的點前一個為止,或者fail鏈的點前一個。 而目標串只走m步!就DP啦~~~~ dp[i][k]表示匹配 i 步 到 k 點的方案數 那轉移方程:dp[i][ch[k][j]]+=dp[i-1][k]; 就可以啦~~~~~~~~~~~}
#include<bits/stdc++.h>#define RG register#define il inline#define N 60010using namespace std;int ch[N][27],f[N],cc,n,k;char s[N*2];bool in[N];void Insert(){ int now=0,len=strlen(s+1);int h=1; while(h<=len){ int c=s[h]-‘A‘; if(!ch[now][c])ch[now][c]=++cc; now=ch[now][c];h++; }in[now]=true;}il void getfail(){queue<int>que; while(!que.empty())que.pop();que.push(0); while(!que.empty()){ RG int u=que.front(); for(RG int i=0;i<26;++i){ if(ch[u][i])que.push(ch[u][i]),f[ch[u][i]]=(u==0?0:ch[f[u]][i]); else ch[u][i]=(u==0?0:ch[f[u]][i]); } in[u]|=in[f[u]]; que.pop(); }return;}#define MOD 10007int qpow(int a,int b){ if(b==1)return a;if(!b)return 1; int tmp=qpow(a,(b>>1)); tmp=(tmp*tmp)%MOD;if(b&1)tmp=(tmp*a)%MOD; return tmp;}int dp[101][N];int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); scanf("%d%d",&n,&k); for(int i=1;i<=n;++i)scanf("%s",s+1),Insert();getfail(); dp[0][0]=1; for(int i=1;i<=k;++i) for(int j=0;j<=cc;++j) if(!in[j]){for(int K=0;K<26;++K){ dp[i][ch[j][K]]+=dp[i-1][j]; if(dp[i][ch[j][K]]>=MOD)dp[i][ch[j][K]]-=MOD;} }int ans=qpow(26,k); for(int i=0;i<=cc;++i)if(!in[i])ans-=(dp[k][i]%MOD),ans=(ans+MOD)%MOD; cout<<ans; return 0;}
BZOJ1030:[JSOI2007]文本產生器