BZOJ 3530 数数【AC自动机+数位dp】

骑猪看日落 2022-08-09 01:53 293阅读 0赞

[Sdoi2014]数数

简单数位dp+简单AC自动机
反正数位DP是队友写的
AC自动机要记录两个值,一个是是否为一个串的结束,即不合法状态,一个是前缀零的情况。

  1. // whn6325689
  2. // Mr.Phoebe
  3. // http://blog.csdn.net/u013007900
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <iomanip>
  7. #include <cstring>
  8. #include <climits>
  9. #include <complex>
  10. #include <fstream>
  11. #include <cassert>
  12. #include <cstdio>
  13. #include <bitset>
  14. #include <vector>
  15. #include <deque>
  16. #include <queue>
  17. #include <stack>
  18. #include <ctime>
  19. #include <set>
  20. #include <map>
  21. #include <cmath>
  22. #include <functional>
  23. #include <numeric>
  24. #pragma comment(linker, "/STACK:1024000000,1024000000")
  25. using namespace std;
  26. #define eps 1e-9
  27. #define PI acos(-1.0)
  28. #define INF 0x3f3f3f3f
  29. #define LLINF 1LL<<50
  30. #define speed std::ios::sync_with_stdio(false);
  31. typedef long long ll;
  32. typedef unsigned long long ull;
  33. typedef long double ld;
  34. typedef pair<ll, ll> pll;
  35. typedef complex<ld> point;
  36. typedef pair<int, int> pii;
  37. typedef pair<pii, int> piii;
  38. typedef vector<int> vi;
  39. #define CLR(x,y) memset(x,y,sizeof(x))
  40. #define CPY(x,y) memcpy(x,y,sizeof(x))
  41. #define clr(a,x,size) memset(a,x,sizeof(a[0])*(size))
  42. #define cpy(a,x,size) memcpy(a,x,sizeof(a[0])*(size))
  43. #define debug(a) cout << #a" = " << (a) << endl;
  44. #define debugarry(a, n) for (int i = 0; i < (n); i++) { cout << #a"[" << i << "] = " << (a)[i] << endl; }
  45. #define mp(x,y) make_pair(x,y)
  46. #define pb(x) push_back(x)
  47. #define lowbit(x) (x&(-x))
  48. #define MID(x,y) (x+((y-x)>>1))
  49. #define getidx(l,r) (l+r | l!=r)
  50. #define ls getidx(l,mid)
  51. #define rs getidx(mid+1,r)
  52. #define lson l,mid
  53. #define rson mid+1,r
  54. template<class T>
  55. inline bool read(T &n)
  56. {
  57. T x = 0, tmp = 1;
  58. char c = getchar();
  59. while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
  60. if(c == EOF) return false;
  61. if(c == '-') c = getchar(), tmp = -1;
  62. while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
  63. n = x*tmp;
  64. return true;
  65. }
  66. template <class T>
  67. inline void write(T n)
  68. {
  69. if(n < 0)
  70. {
  71. putchar('-');
  72. n = -n;
  73. }
  74. int len = 0,data[20];
  75. while(n)
  76. {
  77. data[len++] = n%10;
  78. n /= 10;
  79. }
  80. if(!len) data[len++] = 0;
  81. while(len--) putchar(data[len]+48);
  82. }
  83. //-----------------------------------
  84. const int MAXN=2010;
  85. const int MOD=1e9+7;
  86. const int MAC=10;
  87. int dp[MAXN][MAXN][2];
  88. int n,m,a[MAXN];
  89. char s[MAXN];
  90. struct AC
  91. {
  92. int ch[MAXN][MAC],f[MAXN],sz;
  93. int end[MAXN],zero[MAXN],fa[MAXN];
  94. void init()
  95. {
  96. sz=f[0]=0;
  97. newnode(0);
  98. }
  99. int newnode(int pre)
  100. {
  101. CLR(ch[sz],0);
  102. fa[sz]=pre;
  103. end[sz]=zero[sz]=0;
  104. return sz++;
  105. }
  106. void insert(char *S)
  107. {
  108. int u=0,x;
  109. int n=strlen(S);
  110. for(int i=n-1;i>=0;i--)
  111. {
  112. x=S[i]-'0';
  113. if(!ch[u][x]) ch[u][x]=newnode(u);
  114. u=ch[u][x];
  115. }
  116. end[u]=1;
  117. zero[u]=S[0]=='0';
  118. }
  119. int que[MAXN],front,back;
  120. void getfail()
  121. {
  122. int u,cur,ans=-1;
  123. front=back=0;
  124. for(int i=0;i<MAC;i++)
  125. if(ch[0][i])
  126. {
  127. que[back++]=ch[0][i];
  128. f[ch[0][i]]=0;
  129. }
  130. while(front<back)
  131. {
  132. cur=que[front++];
  133. for(int i=0;i<MAC;i++)
  134. {
  135. u=ch[cur][i];
  136. if(u)
  137. {
  138. que[back++]=u;
  139. f[u]=ch[f[cur]][i];
  140. }
  141. else
  142. ch[cur][i]=ch[f[cur]][i];
  143. end[u] |= end[f[u]];
  144. }
  145. }
  146. }
  147. void DP(int u,int cur,int over)
  148. {
  149. int &ret=dp[u][cur][over];
  150. if(~ret) return ;
  151. if(end[u])
  152. {
  153. int t=0;
  154. if(zero[u]) t=1;
  155. dp[u][cur][0]=dp[u][cur][1]=t;
  156. if(!cur) dp[u][cur][1]=0;
  157. return;
  158. }
  159. if(!cur)
  160. {
  161. dp[u][cur][1]=0;
  162. dp[u][cur][0]=1;
  163. return;
  164. }
  165. ret=0;
  166. for(int c=0; c<MAC; c++)
  167. {
  168. if(over)
  169. {
  170. if(c>=a[cur-1])
  171. {
  172. DP(ch[u][c],cur-1,1);
  173. ret=(ret+dp[ch[u][c]][cur-1][1]) % MOD;
  174. }
  175. else
  176. {
  177. DP(ch[u][c],cur-1,0);
  178. ret=(ret+dp[ch[u][c]][cur-1][0]) % MOD;
  179. }
  180. }
  181. else
  182. {
  183. if(c>a[cur-1])
  184. {
  185. DP(ch[u][c],cur-1, 1);
  186. ret=(ret+dp[ch[u][c]][cur-1][1]) % MOD;
  187. }
  188. else
  189. {
  190. DP(ch[u][c],cur-1, 0);
  191. ret=(ret+dp[ch[u][c]][cur-1][0]) % MOD;
  192. }
  193. }
  194. }
  195. }
  196. } ac;
  197. int main()
  198. {
  199. //freopen("data.txt","r",stdin);
  200. ac.init(); CLR(dp,-1);
  201. scanf("%s",s);
  202. n=strlen(s);
  203. for(int i=0; i<n; i++) a[i]=s[i]-'0';
  204. scanf("%d",&m);
  205. for(int i=1; i<=m; i++)
  206. {
  207. scanf("%s",s);
  208. ac.insert(s);
  209. }
  210. ac.getfail();
  211. ac.DP(0,n,0);
  212. printf("%d\n", dp[0][n][0]-1);
  213. return 0;
  214. }

发表评论

表情:
评论列表 (有 0 条评论,293人围观)

还没有评论,来说两句吧...

相关阅读

    相关 AC 动机

    AC 自动机是 以 TRIE 的结构为基础 ,结合 KMP 的思想 建立的。 简单来说,建立一个 AC 自动机有两个步骤: 基础的 tree结构:将所有的模式串构成一棵

    相关 AC动机

    要学会AC自动机,我们必须知道什么是Trie,也就是字典树。最好对KMP算法也有些了解。Trie树和KMP算法我之前博客都有写过,感兴趣的可以看看。 简单叙述下问题

    相关 AC动机

    今天写一下基本的AC自动机的思想原理和实现。 Aho-Corasick automation,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一。一个常见的例子就是

    相关 bzoj-1030(AC动机+DP

    题意:给你n个匹配串,算出所有长度为m且至少包括1个匹配串的数量; 解题思路:首先根据题意,因为至少包括一个不好弄,根据容斥,我们可以把题目搞成求出所有长度为m不包括匹配串的