1. 程式人生 > >bzoj1030 文本生成器 Trie圖+dp

bzoj1030 文本生成器 Trie圖+dp

spa trie esp using 沒有 ans fail \n col

---恢復內容開始---

套路題

dp[i][j]表示文本第i個字符匹配到trie圖的第j個節點且沒有出現過完整單詞的方案數

拿26^n-dp[n]就好

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define mod 10007
using namespace std;
int n,m,tot,ans=1;
char s[105];
bool ed[6005];
int dp[105][6005];
struct node{
    
int son[26]; int fail; }tr[6005]; void build(char b[]){ int now=0,len=strlen(b+1); for(int i=1;i<=len;i++){ int k=b[i]-A; if(!tr[now].son[k])tr[now].son[k]=++tot; now=tr[now].son[k]; } ed[now]=true; } void getfail(){ queue<int>que;
for(int i=0;i<26;i++){ if(tr[0].son[i]){ que.push(tr[0].son[i]); } } while(!que.empty()){ int u=que.front(); que.pop(); for(int i=0;i<26;i++){ if(!tr[u].son[i]){ tr[u].son[i]=tr[tr[u].fail].son[i];
continue; } tr[tr[u].son[i]].fail=tr[tr[u].fail].son[i]; ed[tr[u].son[i]]|=ed[tr[tr[u].fail].son[i]]; que.push(tr[u].son[i]); } } } void DP(){ dp[0][0]=1; for(int i=1;i<=m;i++){ for(int j=0;j<=tot;j++){ for(int k=0;k<26;k++){ if(!ed[tr[j].son[k]]){ (dp[i][tr[j].son[k]]+=dp[i-1][j])%=mod; } } } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%s",s+1); build(s); } getfail();DP(); for(int i=1;i<=m;i++){ ans*=26; ans%=mod; } for(int i=0;i<=tot;i++){ ans=((ans-dp[m][i])%mod+mod)%mod; } printf("%d\n",ans); return 0; }

bzoj1030 文本生成器 Trie圖+dp