博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BCD Code ZOJ - 3494 AC自动机+数位DP
阅读量:5030 次
发布时间:2019-06-12

本文共 3224 字,大约阅读时间需要 10 分钟。

题意: 

问A到B之间的所有整数,转换成BCD Code后,

有多少个不包含属于给定病毒串集合的子串,A,B <=10^200,病毒串总长度<= 2000.

BCD码这个在数字电路课上讲了,题干也讲的很详细。

 

数位DP的实现是通过0~9 ,并不是通过BCD码

所有我们需要先把字串放入AC自动机,建立一个BCD数组

因为BCD码是一个4位二进制数,但是tire图上全是0,1,

所以对于一个数字,我们的要在转移4次,

如果中间出现了病毒串就return -1 表示不能转移,

BCD【i】【j】表示在AC自动机 i 这个节点转移到数字 j 对应的在AC自动机上的节点标号。

  然后就是简单的数位DP了,然而我写搓了,由于没有前导0所以前导0要处理掉。

但是你不转移的时候,不能 bcd[idx][i] != -1 就直接continue ,

因为有0的情况,i==0 但是(bcd[idx][i] == -1) 但是这个0是前导0所以不影响。

 

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 14 #define pi acos(-1.0) 15 #define eps 1e-9 16 #define fi first 17 #define se second 18 #define rtl rt<<1 19 #define rtr rt<<1|1 20 #define bug printf("******\n") 21 #define mem(a, b) memset(a,b,sizeof(a)) 22 #define name2str(x) #x 23 #define fuck(x) cout<<#x" = "<
<
Q; 83 fail[root] = root; 84 for (int i = 0; i < 2; i++) 85 if (next[root][i] == -1) next[root][i] = root; 86 else { 87 fail[next[root][i]] = root; 88 Q.push(next[root][i]); 89 } 90 while (!Q.empty()) { 91 int now = Q.front(); 92 Q.pop(); 93 if (End[fail[now]]) End[now] = 1; 94 for (int i = 0; i < 2; i++) 95 if (next[now][i] == -1) next[now][i] = next[fail[now]][i]; 96 else { 97 fail[next[now][i]] = next[fail[now]][i]; 98 Q.push(next[now][i]); 99 }100 }101 }102 103 int get_num(int cur, int num) {104 if (End[cur]) return -1;105 int now = cur;106 for (int i = 3; i >= 0; --i) {107 if (End[next[now][1 & (num >> i)]]) return -1;108 now = next[now][1 & (num >> i)];109 }110 return now;111 }112 113 void get_bcd() {114 for (int i = 0; i < cnt; ++i)115 for (int j = 0; j < 10; ++j)116 bcd[i][j] = get_num(i, j);117 }118 119 LL dfs(int pos, int idx, int flag, int limit) {120 if (pos == -1) return 1;121 if (!limit && dp[pos][idx] != -1) return dp[pos][idx];122 int num = limit ? bit[pos] : 9;123 LL ans = 0;124 for (int i = 0; i <= num; ++i) {125 if (flag && i == 0) ans = (ans + dfs(pos - 1, idx, 1, limit && i == num)) % mod;126 else if (bcd[idx][i] != -1) ans = (ans + dfs(pos - 1, bcd[idx][i], 0, limit && i == num)) % mod;127 }128 if (!limit && !flag) dp[pos][idx] = ans;129 return ans;130 }131 132 LL solve() {133 get_bcd();134 int len1 = strlen(num1), len2 = strlen(num2);135 for (int i = len1-1; i>=0; --i) {136 if (num1[i] > '0') {137 num1[i]--;138 break;139 } else num1[i] = '9';140 }141 for (int i = 0; i < len1; ++i) bit[i] = num1[len1 - 1 - i] - '0';142 LL ans1 = dfs(len1 - 1, 0, 1, 1);143 for (int i = 0; i < len2; ++i) bit[i] = num2[len2 - 1 - i] - '0';144 LL ans2 = dfs(len2 - 1, 0, 1, 1);145 return (ans2 - ans1 + mod) % mod;146 }147 148 void debug() {149 for (int i = 0; i < cnt; i++) {150 printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);151 for (int j = 0; j < 26; j++) printf("%2d", next[i][j]);152 printf("]\n");153 }154 }155 } ac;156 157 int main() {158 // FIN;159 sfi(T);160 while (T--) {161 sfi(n);162 ac.init();163 for (int i = 0; i < n; ++i) {164 sfs(buf);165 ac.insert(buf);166 }167 ac.build();168 sffs(num1, num2);169 mem(dp, -1);170 printf("%lld\n", ac.solve());171 }172 return 0;173 }
View Code

 

转载于:https://www.cnblogs.com/qldabiaoge/p/11379682.html

你可能感兴趣的文章
Jmeter性能测试 入门
查看>>
安卓动画有哪几种?他们的区别?
查看>>
Nodejs学习总结 -Express入门(一)
查看>>
web前端优化
查看>>
ssh 连接原理及ssh-keygen
查看>>
vs2013编译qt程序后中文出现乱码
查看>>
【转】IOS数据库操作SQLite3使用详解
查看>>
Android官方技术文档翻译——ApplicationId 与 PackageName
查看>>
设计网站大全
查看>>
JVM CUP占用率过高排除方法,windows环境
查看>>
【转】JAVA字符串格式化-String.format()的使用
查看>>
【转】ButterKnife基本使用--不错
查看>>
【转】VS2012编译出来的程序,在XP上运行,出现“.exe 不是有效的 win32 应用程序” “not a valid win32 application”...
查看>>
函数中关于const关键字使用的注意事项
查看>>
微信架构(转)
查看>>
Web项目中的路径问题
查看>>
js随机数的取整
查看>>
关于解析漏洞
查看>>
十大经典预测算法(六)---集成学习(模型融合算法)
查看>>
用php做一个简单的注册用户功能
查看>>