bzoj1030 文本生成器 Trie圖+dp
阿新 • • 發佈:2018-09-28
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