题目大意:
  给你一个数字串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. oracle字符集查看、修改、版本查看

    .1.先查服务端的字符集   或者 2.再查客户端的字符集 两个字符集(不是语言)一致的话就不会乱码了   详细资料 一.什么是Oracle字符集 Oracle字符集是一个字节数据的解释的符号集合,有 ...

  2. JDK1.8源码TreeMap

    基于红黑树(Red-Black tree)的 NavigableMap 实现:键的排序由构造方法决定:自然排序,Comparator排序:非线程安全(仅改变与现有键关联的值不是结构上的修改):线程安全 ...

  3. aarch64_j1

    JSCookMenu-2.0.4-13.fc26.noarch.rpm 2017-02-14 07:06 37K fedora Mirroring Project Java-WebSocket-1.3 ...

  4. Python Challenge 第 2 关攻略:ocr

    text="那一大推乱码" 方案1 from collections import Counter print(Counter(text)) 方案2 import string & ...

  5. html 列表标签

    1.有序列表 <ol> <li>你好</li> <li>你好</li> <li>你好</li> </ol> ...

  6. centos7.2系统没有eth0网卡

    最近一直在学centos7.5系统,偶然看到虚拟机里有7.2系统所以想练习一下(其实7.2和7.5差不多),但是打开虚拟机之后,发现没有eth0网卡 那没有eth0网卡就无法远程连接ssh,既然遇到了 ...

  7. 洛谷P1266速度限制

    传送门啦 看起来是一个最短路问题,但是引入了速度限制,就要写一下二维最短路了. $ dis[i][j] $ :表示到i这个点,速度为j的最短时间. #include <iostream> ...

  8. Elasticsearch: 权威指南---基础入门

    1.查看方式:GETURL:http://10.10.6.225:9200/?pretty pretty 在任意的查询字符串中增加pretty参数.会让Elasticsearch美化输出JSON结果以 ...

  9. Mybatis入门及Dao开发方式

    本节内容: Mybatis介绍 使用jdbc编程问题总结 Mybatis架构 Mybatis入门程序 Dao的开发方式 SqlMapConfig.xml文件说明 一.Mybatis介绍 MyBatis ...

  10. Django实战(7):改造ProductList界面

    有了上一节关于Django模板的基础,改造界面就很容易理解了.将界面设计师设计的页面中的内容根据复用程度分别放到基础模板base.html和专用模板productlist.html中. depot/t ...