题目大意:
  给你一个数字串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的更多相关文章

  1. CF585F Digits of Number Pi

    题目 把\(s\)串所有长度为\(\lfloor \frac{d}{2}\rfloor\)的子串插入一个ACAM中,之后数位dp就好了,状态是\(dp_{i,j,0/1}\)第\(i\)位,在ACAM ...

  2. 题解 CF585F 【Digits of Number Pi】

    考虑用数位 \(DP\) 来统计数字串个数,用 \(SAM\) 来实现子串的匹配. 设状态 \(f(pos,cur,lenth,lim,flag)\),表示数位的位数,在 \(SAM\) 上的节点,匹 ...

  3. codeforces 464C. Substitutes in Number

    题目链接 C. Substitutes in Number time limit per test 1 second memory limit per test 256 megabytes input ...

  4. 【codeforces 805D】Minimum number of steps

    [题目链接]:http://codeforces.com/contest/805/problem/D [题意] 给你一个字符串; 里面只包括a和b; 让你把里面的"ab"子串全都去 ...

  5. Codeforces C. Split a Number(贪心大数运算)

    题目描述: time limit per test 2 seconds memory limit per test 512 megabytes input standard input output ...

  6. dp --- Codeforces 245H :Queries for Number of Palindromes

    Queries for Number of Palindromes Problem's Link:   http://codeforces.com/problemset/problem/245/H M ...

  7. Codeforces 279D The Minimum Number of Variables 状压dp

    The Minimum Number of Variables 我们定义dp[ i ][ mask ]表示是否存在 处理完前 i 个a, b中存者 a存在的状态是mask 的情况. 然后用sosdp处 ...

  8. Educational Codeforces Round 11 D. Number of Parallelograms 暴力

    D. Number of Parallelograms 题目连接: http://www.codeforces.com/contest/660/problem/D Description You ar ...

  9. Codeforces 980 E. The Number Games

    \(>Codeforces \space 980 E. The Number Games<\) 题目大意 : 有一棵点数为 \(n\) 的数,第 \(i\) 个点的点权是 \(2^i\) ...

随机推荐

  1. SSD固态硬盘检测工具AS SSD参数

    一. 使用AS SSD Benchmark进行查看 包括了4个方面的测试(顺序读写.4K随机读写.64线程4K读写.寻道时间) AS SSD的主要测试,也是网上最常见得到测试成绩的,是它主界面上持续. ...

  2. ansible的几点记录

    user模块的password加密 ansible中user模块的password需要传入加密数据,可以通过这种方式快速加密: To get a sha512 password hash (rando ...

  3. geoserver 启动闪退

    跟JDK版本有关: 比如geoserver2.11需要JDK版本为JDK1.8 windows配置两个jdk环境: 网上有方法,但如果只需要满足geoserver的话,可以只安装jdk(注意jdk和j ...

  4. OKR.2019

    转眼又一年过去了,回顾审视一年的得失,规划下一年的奋斗目标.Review And Planning,让全新的2019迎来全新的自己. O1 学习软件开发技术知识 KR1.1 阅读<CLR via ...

  5. CSS — 贝塞尔曲线(cubic-bezier)

    cubic-bezier 又称三次贝塞尔,主要是为 animation 生成速度曲线的函数,规定是 cubic-bezier(<x1>, <y1>, <x2>, & ...

  6. Flask form

    用户登录 #!/usr/bin/env python # -*- coding:utf- -*- from flask import Flask, render_template, request, ...

  7. JMeter接口&性能测试

    JMeter接口测试 目前最新版本发展到5.0版本,需要Java7以上版本环境,下载解压目录后,进入\apache-jmeter-5.0\bin\,双击ApacheJMeter.jar文件启动JMem ...

  8. HBase(五)HBase的API操作

    一.项目环境搭建 新建 Maven Project,新建项目后在 pom.xml 中添加依赖: <dependency> <groupId>org.apache.hbase&l ...

  9. 【LOJ】#2445. 「NOI2011」道路修建

    题解 看完题目我的第一个反应是--要求最小花费的方案?!怎么求??? 然后我把题读完了.好吧. 记录一下size就行,比NOIP普及组还要不如的题= = 代码 #include <iostrea ...

  10. 常用网络命令(windows)

      Ping命令的常用参数选项 ·ping IP –t 连续对IP地址执行Ping命令,直到被用户以Ctrl+C中断. ·ping IP -l 3000 指定Ping命令中的数据长度为3000字节,而 ...