[CodeForces-585F]Digits of Number Pi
题目大意:
给你一个数字串s,一个序列范围l和r,(l和r的数字位数为d)求l到r中有多少个数,满足它的长度为d/2的子串,能够在s中被匹配。
思路:
首先将s中每一个长度为d/2的子串插入后缀自动机。
然后数位DP。
f[i][j]中第一维表示当前树与l和r的关系,包含四个状态,用二进制表示,每一位对应与l和r的不同关系。
第二维表示当前状态下每个结点匹配到的数的个数。
每一个数位的状态由上一个数位转移而来,我们用两个DP数组f和g滚动实现。
用o表示当前枚举的数字,用to表示数字所对应的第一维的状态,则转移方程为f[to[o]][p]=sum(f[j][par[p]])
然而一开始写AC自动机用的是指针,然后又是各种不方便,所以又用vector很粗糙地实现了结点的遍历。故常数巨大。
#pragma GCC optimize("O3")
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
const int mod=1e9+;
const int N=,D=;
char s[N],l[D],r[D];
int n,d;
class AhoCorasickAutomaton {
private:
static const int SIGMA_SIZE=;
struct Node {
Node *ch[SIGMA_SIZE],*fail;
bool isEnd;
int id;
Node(const int i) {
memset(ch,,sizeof ch);
fail=NULL;
isEnd=false;
id=i;
}
};
Node *root;
std::vector<Node*> v;
int idx(const char ch) {
return ch-'';
}
int f[][N*D>>],g[][N*D>>];
//第一维表示与l和r的关系
public:
AhoCorasickAutomaton() {
root=new Node(v.size());
v.push_back(root);
}
void insert(char s[],const int len) {
Node *p=root;
for(int i=;i<len;i++) {
const int w=idx(s[i]);
if(!p->ch[w]) {
p->ch[w]=new Node(v.size());
v.push_back(p->ch[w]);
}
p=p->ch[w];
}
p->isEnd=true;
}
void getFail() {
std::queue<Node*> q;
root->fail=root;
for(int i=;i<SIGMA_SIZE;i++) {
if(root->ch[i]) {
root->ch[i]->fail=root;
q.push(root->ch[i]);
} else {
root->ch[i]=root;
}
}
while(!q.empty()) {
Node *p=q.front();
q.pop();
for(int i=;i<SIGMA_SIZE;i++) {
if(p->ch[i]) {
p->ch[i]->fail=p->fail->ch[i];
q.push(p->ch[i]);
} else {
p->ch[i]=p->fail->ch[i];
}
}
}
Node *end=new Node(v.size());
for(unsigned i=;i<v.size();i++) {
Node *p=v[i];
for(int i=;i<SIGMA_SIZE;i++) {
if(p->ch[i]->isEnd) {
p->ch[i]=end;
}
}
}
for(int i=;i<SIGMA_SIZE;i++) {
end->ch[i]=end;
}
v.push_back(end);
}
int dp() {
g[][]=;
int to[];
for(int i=;i<d;i++) {
for(int i=;i<;i++) {
for(unsigned j=;j<v.size();j++) {
f[i][j]=;
}
}
for(int j=;j<;j++) {
int st=(j&)?:idx(l[i]),en=(j>)?:idx(r[i]);//确定当前数位数字的上下界
for(int i=st;i<=en;i++) to[i]=0b11;//默认是在l和r之间
if(~j&) to[st]&=0b10;//如果比l小
if(j<) to[en]&=0b01;//如果比r大
//用&是因为有可能st=en
for(unsigned k=;k<v.size();k++) {
if(!g[j][k]) continue;
for(int o=st;o<=en;o++) {//在当前数位的范围寻找子结点
(f[to[o]][v[k]->ch[o]->id]+=g[j][k])%=mod;
}
}
}
std::swap(f,g);
}
int ret=;
for(int i=;i<;i++) {
ret=(ret+g[i][v.size()-])%mod;
}
return ret;
}
};
AhoCorasickAutomaton acam;
int main() {
scanf("%s%s%s",s,l,r);
n=strlen(s),d=strlen(l);
for(int i=;i<=n-d/;i++) {
acam.insert(&s[i],d/);
}
acam.getFail();
printf("%d\n",acam.dp());
return ;
}
[CodeForces-585F]Digits of Number Pi的更多相关文章
- CF585F Digits of Number Pi
题目 把\(s\)串所有长度为\(\lfloor \frac{d}{2}\rfloor\)的子串插入一个ACAM中,之后数位dp就好了,状态是\(dp_{i,j,0/1}\)第\(i\)位,在ACAM ...
- 题解 CF585F 【Digits of Number Pi】
考虑用数位 \(DP\) 来统计数字串个数,用 \(SAM\) 来实现子串的匹配. 设状态 \(f(pos,cur,lenth,lim,flag)\),表示数位的位数,在 \(SAM\) 上的节点,匹 ...
- codeforces 464C. Substitutes in Number
题目链接 C. Substitutes in Number time limit per test 1 second memory limit per test 256 megabytes input ...
- 【codeforces 805D】Minimum number of steps
[题目链接]:http://codeforces.com/contest/805/problem/D [题意] 给你一个字符串; 里面只包括a和b; 让你把里面的"ab"子串全都去 ...
- Codeforces C. Split a Number(贪心大数运算)
题目描述: time limit per test 2 seconds memory limit per test 512 megabytes input standard input output ...
- dp --- Codeforces 245H :Queries for Number of Palindromes
Queries for Number of Palindromes Problem's Link: http://codeforces.com/problemset/problem/245/H M ...
- Codeforces 279D The Minimum Number of Variables 状压dp
The Minimum Number of Variables 我们定义dp[ i ][ mask ]表示是否存在 处理完前 i 个a, b中存者 a存在的状态是mask 的情况. 然后用sosdp处 ...
- Educational Codeforces Round 11 D. Number of Parallelograms 暴力
D. Number of Parallelograms 题目连接: http://www.codeforces.com/contest/660/problem/D Description You ar ...
- Codeforces 980 E. The Number Games
\(>Codeforces \space 980 E. The Number Games<\) 题目大意 : 有一棵点数为 \(n\) 的数,第 \(i\) 个点的点权是 \(2^i\) ...
随机推荐
- 基于Netty4.1.29.Final的helloworld实现.使用idea
服务端: //服务端 public class Server { public static void main(String[] args) { //创建两个线程组 EventLoopGroup c ...
- JS日期与字符串相互转换!!
一 日期转字符串 dateToString: function(date){ var year = date.getFullYear(); var month =(date.getMonth() + ...
- QEMU漏洞挖掘
转载:https://www.tuicool.com/articles/MzqYbia qemu是一个开源的模拟处理器硬件设备的全虚拟化仿真器和虚拟器. KVM(kernel virtual mach ...
- python3 asyncio官方文档中文版
事件循环基类 事件循环基类 事件循环是由asyncio提供的核心执行装置.它提供了多种服务,包括: 注册.执行和关闭延时调用(超时) 为各种通信创建客户端和服务端传输 为一个外部程序通信启动子进程和相 ...
- checkbox 全选和取消
//全选 $("#checkall").click(function () { if (this.checked) { //如果当前点击的多选框被选中 $('input[type= ...
- HDU 6199 2017沈阳网络赛 DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6199 题意:n堆石子,Alice和Bob来做游戏,一个人选择取K堆那么另外一个人就必须取k堆或者k+1 ...
- jQuery简单介绍
一.jQuery介绍 jQuery是一个轻量级的.兼容多浏览器的JavaScript库. jQuery使用户能够更方便地处理HTML Document.Events.实现动画效果.方便地进行Ajax交 ...
- python基础--hashlib模块
hashlib模块用于加密操作,代替了md5和sha模块, 主要提供SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法. # -*- coding:utf-8 - ...
- python基础-类的继承
继承:承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”.“父类. 继承的过程,就是从一般到特殊的过程.要实现继承,可以通过“继承”(Inheritance)和“组合”(Compositio ...
- caffe可视化
1.画网络图 假