思路

看到多个子串并且不能包含的情况,想到了AC自动机

但是题目多了一个不能大于给出的n的限制条件,联想数位dp的过程,设f[i][j][0/1]表示在第i位,AC自动机的第j个节点,数位有/无限制的方案数

dp方程就是对应的转移到子节点即可,不向有标记的节点转移

注意如果跳fail能够跳到限制节点,就也不能转移,因为fail树上的父节点是子节点的子串,如果父节点是单词节点,子节点一定包含单词

另外题目中的数不能出现前导零,所以从根节点向子节点转移时不能转移到根的0号子节点

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define int long long
const int MOD = 1000000007;
using namespace std;
int trie[1501][10],Nodecnt,fail[1501],mark[1501],root,f[1201][1501][2],lens,lent;
char s[1501],t[1501];
void insert(char *s,int len){
int o=root;
for(int i=1;i<=len;i++){
if(!trie[o][s[i]-'0'])
trie[o][s[i]-'0']=++Nodecnt;
o=trie[o][s[i]-'0'];
}
mark[o]++;
}
void get_fail(void){
queue<int> q;
for(int i=0;i<10;i++){
if(trie[root][i]){
fail[trie[root][i]]=root;
q.push(trie[root][i]);
}
}
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=0;i<10;i++){
if(trie[x][i]){
fail[trie[x][i]]=trie[fail[x]][i];
// mark[trie[x][i]]|=mark[trie[fail[x]][i]];
q.push(trie[x][i]);
}
else{
trie[x][i]=trie[fail[x]][i];
}
}
}
}
void getban(void){
for(int i=0;i<=Nodecnt;i++){
int p=i;
for(;p;p=fail[p])
if(mark[p]){
mark[i]=true;
break;
}
}
}
int dp(void){
for(int i=0;i<lens;i++){
for(int j=0;j<=Nodecnt;j++){
if(f[i][j][0]){
for(int k=0;k<s[i+1]-'0';k++)
if(!mark[trie[j][k]])
f[i+1][trie[j][k]][1]=(f[i+1][trie[j][k]][1]+f[i][j][0])%MOD;
if(!mark[trie[j][s[i+1]-'0']])
f[i+1][trie[j][s[i+1]-'0']][0]=(f[i+1][trie[j][s[i+1]-'0']][0]+f[i][j][0])%MOD;
}
if(f[i][j][1]){
for(int k=0;k<10;k++)
if(!mark[trie[j][k]])
f[i+1][trie[j][k]][1]=(f[i+1][trie[j][k]][1]+f[i][j][1])%MOD;
}
if(!j){
if(!i){
for(int k=1;k<s[i+1]-'0';k++)
if(!mark[trie[j][k]])
f[i+1][trie[j][k]][1]=(1+f[i+1][trie[j][k]][1])%MOD;
if(!mark[trie[j][s[i+1]-'0']])
f[i+1][trie[j][s[i+1]-'0']][0]=(1+f[i+1][trie[j][s[i+1]-'0']][0])%MOD;
}
else{
for(int k=1;k<10;k++)
if(!mark[trie[j][k]])
f[i+1][trie[j][k]][1]=(1+f[i+1][trie[j][k]][1])%MOD;
}
}
}
}
int ans=0;
for(int i=0;i<=Nodecnt;i++)
ans=(f[lens][i][0]+f[lens][i][1]+ans)%MOD;
return ans;
}
signed main(){
scanf("%s",s+1);
lens=strlen(s+1);
int n;
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%s",t+1);
lent=strlen(t+1);
insert(t,lent);
}
get_fail();
getban();
// for(int i=1;i<=Nodecnt;i++)
// if(mark[i])
// printf("%d!\n",i);
printf("%lld\n",dp());
return 0;
}

P3311 [SDOI2014]数数的更多相关文章

  1. 【BZOJ】【3530】【SDOI2014】数数

    AC自动机/数位DP orz zyf 好题啊= =同时加深了我对AC自动机(这个应该可以叫Trie图了吧……出边补全!)和数位DP的理解……不过不能自己写出来还真是弱…… /************* ...

  2. BZOJ3530: [Sdoi2014]数数

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 322  Solved: 188[Submit][Status] ...

  3. 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 682  Solved: 364 Description 我们称一 ...

  4. BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]

    3530: [Sdoi2014]数数 题意:\(\le N\)的不含模式串的数字有多少个,\(n=|N| \le 1200\) 考虑数位DP 对于长度\(\le n\)的,普通套路DP\(g[i][j ...

  5. 「SDOI2014」数数 解题报告

    「SDOI2014」数数 题目描述 我们称一个正整数 \(N\) 是幸运数,当且仅当它的十进制表示中不包含数字串集合 \(S\) 中任意一个元素作为其子串. 例如当 \(S=(\)22, 333, 0 ...

  6. 3530: [Sdoi2014]数数

    3530: [Sdoi2014]数数 链接 分析: 对给定的串建立AC自动机,然后数位dp.数位dp的过程中,记录当前在AC自动机的哪个点上,保证不能走到出现了给定串的点. 代码: #include& ...

  7. [SDOI2014]数数 --- AC自动机 + 数位DP

    [SDOI2014]数数 题目描述: 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串. 例如当S=(22,333,0233)时,233是幸运数,2333 ...

  8. bzoj [Sdoi2014]数数 AC自动机上dp

    [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1264  Solved: 636[Submit][Status][Discu ...

  9. [Sdoi2014]数数[数位dp+AC自动机]

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 834  Solved: 434[Submit][Status][ ...

  10. [bzoj3530][Sdoi2014]数数_AC自动机_数位dp

    数数 bzoj-3530 Sdoi-2014 题目大意:给你一个整数集合,求所有不超过n的正整数,是的它的十进制表示下不能再一段等于集合中的任意数. 注释:$1\le n \le 1200$,$1\l ...

随机推荐

  1. 谈谈CSS中一些比较"偏门"的小知识

    前面我写了:谈谈html中一些比较"偏门"的知识,现在这篇(主要)想谈谈个人所见的CSS一些小知识点,加深印象:同时也希望有需要的人能有收获! 1.常见的浏览器内核: 以IE为代表 ...

  2. 【Linux学习一】命令查看与帮助

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 一.Linux执行命令流程:shell->bash(解释器 执行 ...

  3. c# 设置控件的前景颜色和背景颜色

    AutoSize:设置为false取消自动计算尺寸功能,控件的大小则按照设定的Size来呈现,设置为true自动计算大小 TextAlign:设置对齐方式 // // 摘要: // 用默认的所有者运行 ...

  4. AtCoder Beginner Contest 044 A - 高橋君とホテルイージー / Tak and Hotels (ABC Edit)

    Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement There is a hotel with ...

  5. JustOj 1910: 人见人爱A+B

    [提交][状态][讨论版] 题目描述 北大的acm上面已经有10来道A+B的题目了,相信这些题目曾经是大家的最爱,希望今天的这个A+B能给大家带来好运,也希望这个题目能唤起大家对ACM曾经的热爱.   ...

  6. Symfony2 学习笔记之控制器

    一个controller是你创建的一个PHP函数,它接收HTTP请求(request)并创建和返回一个HTTP回复(Response).回复对象(Response)可以是一个HTML页面,一个XML文 ...

  7. git push跳过用户名和密码认证配置教程

    在使用git commit命令将修改从暂存区提交到本地版本库后,只剩下最后一步将本地版本库的分支推送到远程服务器上对应的分支了,如果不清楚版本库的构成,可以查看我的另一篇,git 仓库的基本结构. 新 ...

  8. Python爬虫——小说

    #encoding:utf8 import re import urllib2 url = 'http://www.23us.com/html/55/55304/' request = urllib2 ...

  9. LogUtil工具

    package com.develop.web.util; import java.util.concurrent.locks.ReentrantLock; import org.slf4j.Logg ...

  10. bzoj2120 / P1903 [国家集训队]数颜色 / 维护队列(带修改莫队)

    P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队 在原有指针$(l,r)$上又添加了时间指针$t$ 贴一段dalao的解释 带修改的莫队,和原版莫队相比,多了一个时间轴 原版莫队是将区间( ...