[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\) ...
随机推荐
- linux中set、unset、export、env、declare,readonly的区别以及用法
set命令显示当前shell的变量,包括当前用户的变量; env命令显示当前用户的变量; export命令显示当前导出成用户变量的shell变量. 每个shell有自己特有 ...
- Linux USB驱动学习总结(一)---- USB基本概念及驱动架构
USB,Universal Serial Bus(通用串行总线),是一个外部总线标准,用于规范电脑与外部设备的连接和通讯.是应用在PC领域的接口技术.USB接口支持设备的即插即用和热插拔功能.USB是 ...
- Nginx常见错误与问题之解决方法技术指南
Nginx常见错误与问题之解决方法技术指南. 安装环境: 系统环境:redhat enterprise 6.5 64bit 1.Nginx 常见启动错误 有的时候初次安装nginx的时候会报这样的 ...
- MySQL5.7之多源复制&Nginx中间件(上)【转】
有生之年系列----MySQL5.7之多源复制&Nginx中间件(上)-wangwenan6-ITPUB博客http://blog.itpub.net/29510932/viewspace-1 ...
- 【Andorid开发框架学习】之Volley入门
Volley是Android平台上的网络通信库,能使网络通信更快,更简单,更健壮.Volley特别适合数据量不大但是通信频繁的场景.在listView显示图片这方面,使用volley也是比较好的,不必 ...
- Jmeter 接口测试-请求 Headers 与传参方式
1.添加信息表头. 注意:1.使用Parameters时,Content-Type要么不传,要么传application/x-www-form-urlencoded,因为不传时默认值就是applica ...
- Linux sudo 配置
1.配置sudo权限 sudo配置信息保存在 /etc/sudoers 文件中,可以使用vi修改.但使用vi修改需要给root用户设置权限,可以使用 visudo 直接修改. visudo 复制这行将 ...
- [USACO18FEB]Snow Boots S
提供一种无脑DP做法 题目中大概有这么些东西:位置,穿鞋,跑路 数据小,那么暴力开数组暴力DP吧 设dp[i][j]表示穿着鞋子j,到达位置i是否可行 无脑转移 枚举位置,正在穿哪双鞋,换成哪双走出去 ...
- R语言学习笔记:sort、rank、order、arrange排序函数
R语言中排序有几个基本函数:sort().rank().order().arrange() 一.总结 sort()函数是对向量进行从小到大的排序 rank()函数返回的是对向量中每个数值对应的秩 or ...
- 题解-python-CodeForces 227A
codeforces题目,用python写 本题输入三个点坐标,考察叉积,若大于0则right,小于0则left,等于0则towards 代码: a = raw_input().split() b = ...