首页 > 代码库 > hdu2825Wireless Password(ac+dp)

hdu2825Wireless Password(ac+dp)

链接

状压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 }
View Code