状压dp+ac
dp[i+1][next[j]][st|tt]表示第i+1长度结点为next[j]状态为st|tt的时候的ans;
dp[i+1][next[j]][st|tt]+=dp[i][j][tt]; st记录当前结点是否为给定单词的结束点
后一维用01状态表示截止到目前结点为止所包含的单词数量。
需要修改ac模板的一个地方,val[u]|=val[fail[u]];
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 115 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 const int child_num = 26; 18 const int mod = 20090717; 19 class AC 20 { 21 private: 22 int ch[N][child_num]; 23 int fail[N]; 24 int Q[N]; 25 int val[N]; 26 int sz; 27 int id[128]; 28 int dp[30][N][1<<10]; 29 public: 30 void init() 31 { 32 fail[0] =0; 33 for(int i = 0 ;i < child_num ; i++) 34 id[i+‘a‘] = i; 35 } 36 void reset() 37 { 38 memset(val,0,sizeof(val)); 39 memset(ch[0],0,sizeof(ch[0])); 40 //memset(fail,0,sizeof(fail)); 41 sz = 1; 42 } 43 void insert(char *a,int key) 44 { 45 int p = 0; 46 for(; *a ; a++) 47 { 48 int d = id[*a]; 49 if(ch[p][d]==0) 50 { 51 memset(ch[sz],0,sizeof(ch[sz])); 52 ch[p][d] = sz++; 53 } 54 p = ch[p][d]; 55 } 56 val[p] = (1<<key); 57 } 58 void construct() 59 { 60 int i,head=0,tail = 0; 61 for(i = 0 ;i < child_num ; i++) 62 { 63 if(ch[0][i]) 64 { 65 fail[ch[0][i]] = 0; 66 Q[tail++] = ch[0][i]; 67 } 68 } 69 while(head!=tail) 70 { 71 int u = Q[head++]; 72 val[u]|=val[fail[u]]; 73 for(i = 0 ;i < child_num ;i++) 74 { 75 if(ch[u][i]) 76 { 77 fail[ch[u][i]] = ch[fail[u]][i]; 78 Q[tail++] = ch[u][i]; 79 } 80 else ch[u][i] = ch[fail[u]][i]; 81 } 82 } 83 } 84 void work(int n,int k,int m) 85 { 86 int i,j,g,o; 87 for(i = 0 ; i <= n ;i++) 88 for(j = 0 ; j <= sz ; j++) 89 for(g = 0 ;g <=(1<<m) ; g++) 90 dp[i][j][g] = 0; 91 dp[0][0][0] = 1; 92 for(i = 0; i < n ;i++) 93 for(j = 0; j < sz ; j++) 94 { 95 for(int e =0 ; e < (1<<m) ; e++) 96 { 97 if(!dp[i][j][e]) continue; 98 for(g = 0 ;g < child_num ; g++) 99 { 100 o = 0; 101 if(val[ch[j][g]]) 102 { 103 o = val[ch[j][g]]; 104 } 105 dp[i+1][ch[j][g]][e|o]=(dp[i+1][ch[j][g]][e|o]+dp[i][j][e])%mod; 106 } 107 } 108 } 109 int ans = 0; 110 for(i = 0 ; i < sz;i ++) 111 { 112 for(j = 0 ;j < (1<<m) ; j++) 113 { 114 if(!dp[n][i][j]) continue; 115 int o =0 ; 116 for(g = 0 ;g < m ; g++) 117 if(j&(1<<g)) o++; 118 if(o>=k) 119 ans = (ans+dp[n][i][j])%mod; 120 } 121 } 122 printf("%d\n",ans); 123 } 124 }ac; 125 char vir[15]; 126 int main() 127 { 128 int n,m,k,i; 129 ac.init(); 130 while(scanf("%d%d%d",&n,&m,&k)!=EOF) 131 { 132 if(!n&&!m&&!k) break; 133 ac.reset(); 134 for(i = 1; i <= m; i++) 135 { 136 scanf("%s",vir); 137 ac.insert(vir,i-1); 138 } 139 ac.construct(); 140 ac.work(n,k,m); 141 } 142 return 0; 143 }
hdu2825Wireless Password(ac+dp),布布扣,bubuko.com
hdu2825Wireless Password(ac+dp)
原文:http://www.cnblogs.com/shangyu/p/3736021.html