[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\) ...
随机推荐
- 数据库名(DB_NAME)、实例名(Instance_name)、以及操作系统环境变量(ORACLE_SID)
数据库名(DB_NAME).实例名(Instance_name).以及操作系统环境变量(ORACLE_SID) 在ORACLE7.8数据库中只有数据库名(db_name)和数据库实例名(instanc ...
- 利用正则表达式去除所有html标签,只保留文字
后台将富文本编辑器中的内容返回到前端时如果带上了标签,这时就可以利用这种方法只保留文字. 标签的格式有以下几种 1.<div class="test"></div ...
- ubuntu16.04 eclipse+pydev 配置
参考:http://blog.csdn.net/bluish_white/article/details/56509446,http://blog.csdn.net/qing101hua/articl ...
- sqlite3 的insert记录项思路
sqlite3 的insert记录项思路 1.组合一个insert的sql语句 2.判断是否需要立即执行,若不是立刻执行的语句,则插入到待处理的链表中,供后续事务处理时提交.必须有一个专门线程来对事务 ...
- 使用Cache缓存
存放位置:服务器内存,用于频繁访问且不轻易更改的内容缓存. string CacheKey = "CT1"; //检索指定项, object objModel = Cache.Ge ...
- React 学习二 组件
React的一个最大的特点就是组件化的开发模式.今天就来试一下: <!DOCTYPE html> <html> <head> <meta charset=&q ...
- MySQL基础 - 视图
创建视图: 假设要将posts表的前十条数据作为视图 mysql> CREATE VIEW view_test AS SELECT * FROM POSTS LIMIT 10; 使用: 可以把视 ...
- JS实现点击图片,在浏览器中查看。
工作中遇到要实现点击图片查看的功能,从网上找了一段js代码,可以用. <img src="/pic/${pictureCertificate}" alt="凭证&q ...
- 自定义Adapter为什么会重复多轮调用getView?——原来是ListView.onMeasure在作祟
相信很多人在使用自定义Adapter的时候都遇到这样的问题: 假设Adapter数据源中只有30个Item,理论上每显示一个新的Item的时候就会调用一次getView,均显示一次的话是要调用getV ...
- mysql 闪回测试
由于前面出现过几个需求,或者误操作,或者测试,需要我把某张表恢复到操作之前的一个状态,前面在生产中有过几次经历,实在太痛苦了,下面是一张表被误删除了,我的步骤是: 1 用全备恢复整个库(恢复到其他环 ...