HDU 2825 AC自動機+狀壓DP
阿新 • • 發佈:2018-11-14
這道題是說給定m個單詞,求最少包含q個單詞,長度為n的單詞的種類。這道題我們先對單詞建一個Trie,然後在樹上dp,dp[i][j][k]表示長度為i在樹上的第j個節點,使用了第K種方案的結果,第K種方案的意思是K的二進位制中為1的部分表示使用過了,為0的部分表示沒有使用過,最後將長度為n的使用的單次數量>=p的方案數加起來就行
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h> #include <queue> #include <map> using namespace std; #define LL long long const int maxnode=1100; const int sigma_size=27; const int mod=20090717; char s[1005]; int sz=1; struct Node { int son[sigma_size]; int val,fail; }ch[maxnode]; struct AC { queue<int>Q; void init(int x) {ch[x].fail=ch[x].val=0;memset(ch[x].son,0,sizeof(ch[x].son));} int idx(char c) {return c-'a';} void insert(char s[],int v) { int u=0,n=strlen(s); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u].son[c]) { init(sz); ch[u].son[c]=sz++; } u=ch[u].son[c]; } ch[u].val=v; } void build() { for(int i=0;i<sigma_size;i++) if(ch[0].son[i]) Q.push(ch[0].son[i]); while(!Q.empty()) { int now=Q.front();Q.pop(); int fail=ch[now].fail; for(int i=0;i<sigma_size;i++) { int nxt=ch[now].son[i]; if(nxt) { ch[nxt].fail=ch[fail].son[i]; Q.push(nxt); } else ch[now].son[i]=ch[fail].son[i]; ch[ch[now].son[i]].val|=ch[ch[ch[now].fail].son[i]].val; } } } }ans; int num[1<<11+5]; LL dp[30][105][1025]; int main() { ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); for(int i=1;i<(1<<10);i++) { for(int j=0;j<10;j++) { if(i&(1<<j)) num[i]++; } } int n,m,q; while(cin>>n>>m>>q){ if(n==0&&m==0&&q==0) break; sz=1; ans.init(0); for(int i=0;i<m;i++) { cin>>s; ans.insert(s,(1<<i)); } for(int i=0;i<=n;i++) { for(int j=0;j<sz;j++) { for(int k=0;k<=(1<<m);k++) { dp[i][j][k]=0; } } } ans.build(); dp[0][0][0]=1; for(int i=0;i<n;i++) { for(int j=0;j<sz;j++) { for(int k=0;k<(1<<m);k++) { if(dp[i][j][k]>0) { for(int x=0;x<26;x++) { dp[i+1][ch[j].son[x]][k|ch[ch[j].son[x]].val]+=dp[i][j][k]; if(dp[i+1][ch[j].son[x]][(k|ch[ch[j].son[x]].val)]>=mod) dp[i+1][ch[j].son[x]][k|ch[ch[j].son[x]].val]-=mod; } } } } } LL ans=0; for(int i=0;i<(1<<m);i++) { if(num[i]>=q) { for(int j=0;j<sz;j++) { ans=(ans+dp[n][j][i])%mod; } } } cout<<ans<<"\n"; } return 0; }