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

 

你可能感兴趣的:(password)