poj1625Censored!(AC自动机+dp)

链接

第一次做这种题目,参考了下题解,相当于把树扯直了做DP,估计这一类题都是这个套路吧。

状态方程dp[i][next] = dp[i][next]+dp[i][j] ;dp[i][j]表示长度为i的第J个结点的时候满足题意的num,next为当前j点所能走到的下一个合法的结点。

需要用高精度,看到一些规范的高精度写法,觉得不错,有空整理下来。

不知道是不是我理解错了,按理说字符串病毒长度不应超过10.。但开到55依旧RE,开550AC。。。

  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 110

 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 = 110;

 18 const int BASE = 10000;

 19 const int DIG = 4;

 20 char s[N*100],vir[550];

 21 int id[2024];

 22 struct bignum

 23 {

 24      int a[110],len;

 25      bignum()

 26      {

 27          memset(a,0,sizeof(a));

 28          len = 1;

 29      }

 30      bignum(int v)

 31      {

 32          memset(a,0,sizeof(a));

 33          len = 0;

 34          do

 35          {

 36              a[len++] = v%BASE;

 37              v/=BASE;

 38          }while(v);

 39      }

 40      /*bignum(const char s[])

 41      {

 42          memset(a,0,sizeof(a));

 43          int k = strlen(s);

 44          len = k/DIG;

 45          if(k%DIG) len++;

 46          int cnt = 0;

 47          for(int i = k-1;  i >= 0 ; i-=DIG)

 48          {

 49              int t = 0;

 50              int kk = i-DIG+1;

 51              if(kk<0) kk =0;

 52              for(int j = kk ; j <= i ; j++)

 53              t = t*10+s[j]-'0';

 54              a[cnt++] = t;

 55          }

 56      }*/

 57      bignum operator + (const bignum &b)const

 58      {

 59          bignum res;

 60          res.len = max(len,b.len);

 61          int i;

 62          for(i = 0 ; i < res.len ;i ++)

 63          res.a[i] = 0;

 64          for(i = 0 ; i < res.len ; i++)

 65          {

 66              res.a[i] += ((i<len)?a[i]:0)+((i<b.len)?b.a[i]:0);

 67              res.a[i+1] += res.a[i]/BASE;

 68              res.a[i] = res.a[i]%BASE;

 69          }

 70          if(res.a[res.len]>0) res.len++;

 71          return res;

 72      }

 73      void output()

 74      {

 75          printf("%d",a[len-1]);

 76          for(int i = len-2 ; i >=0 ; i--)

 77          printf("%04d",a[i]);

 78          printf("\n");

 79      }

 80 }dp[110][110];

 81 class AC

 82 {

 83     private:

 84     int ch[N][child_num];

 85     int Q[N];

 86     int val[N];

 87     int fail[N];

 88     //int id[N];

 89     int sz;

 90     public :

 91     void init()

 92     {

 93         fail[0] = 0;

 94         //for(int i = 0 ;i < child_num-32 ; i++)

 95         //id[i+32] = i;

 96     }

 97     void reset()

 98     {

 99         memset(val,0,sizeof(val));

100         memset(fail,0,sizeof(fail));

101         memset(ch[0],0,sizeof(ch[0]));

102         sz = 1;

103     }

104     void insert(char *a,int key)

105     {

106         int k = strlen(a),p = 0;

107         for(int i = 0 ; i < k ;i++)

108         {

109             int d = id[a[i]];

110             if(ch[p][d]==0)

111             {

112                 memset(ch[sz],0,sizeof(ch[sz]));

113                 ch[p][d] = sz++;

114             }

115             p = ch[p][d];

116         }

117         val[p] = key;

118     }

119     void construct(int n)

120     {

121         int i,head=0,tail = 0;

122         for(i = 0; i < n ; i++)

123         {

124             if(ch[0][i])

125             {

126                 Q[tail++] = ch[0][i];

127                 fail[ch[0][i]] = 0;

128             }

129         }

130         while(head!=tail)

131         {

132             int u = Q[head++];

133             val[u]|=val[fail[u]];

134             for(i = 0 ; i < n ; i++)

135             {

136                 if(ch[u][i])

137                 {

138                     Q[tail++] = ch[u][i];

139                     fail[ch[u][i]] = ch[fail[u]][i];

140                 }

141                 else ch[u][i] = ch[fail[u]][i];

142             }

143         }

144     }

145     void work(int m,int n)

146     {

147         int i,j,g;

148         for(i = 1; i <= m ;i++)

149             for(j = 0 ;j <= sz; j++)

150             dp[i][j] = bignum(0);

151         dp[0][0] = bignum(1);

152         for(i = 0 ; i < m ;i++)

153         {

154             for(j = 0 ; j < sz ;j++)

155             for(g = 0 ; g < n ; g++)

156             if(!val[ch[j][g]])

157             {

158                 dp[i+1][ch[j][g]]=dp[i+1][ch[j][g]]+dp[i][j];

159             }

160         }

161         bignum ans = bignum(0);

162         for(j = 0 ;j < sz ; j++)

163         ans=ans+dp[m][j];

164         ans.output();

165     }

166 }ac;

167 int main()

168 {

169     int n,m,i,p;

170     ac.init();

171     while(cin>>n>>m>>p)

172     {

173         cin>>s;

174         for(i = 0 ; i < n; i++)

175         id[s[i]] = i;

176         ac.reset();

177         for(i = 1;i <= p; i++)

178         {

179             scanf("%s",vir);

180             ac.insert(vir,1);

181         }

182         ac.construct(n);

183         ac.work(m,n);

184     }

185     return 0;

186 }
View Code

 

你可能感兴趣的:(AC自动机)