CSAcademy Prefix Suffix Counting 题解

题意

给你两个数字\(N\)和\(M\),现在\(K\)表示\(M\)的位数。问你从\(1\)到\(N\),有多少个数字满足\(M\)同时是它的前\(K\)个数字和后\(K\)个数字。

思路

我们现在假设\(N\)和\(M\)都是字符串,如果没有特别提及,都作为字符串处理。

假设有一个数字\(S\)大于等于\(1\)小于等于\(N\),我们可以分类讨论它的情况:(同样\(S\)作为字符串处理)

  1. \(S\)的长度大于等于\(2K\),那么前缀和后缀不会互相影响,中间的空出的没填部分在满足这个数字的值小于等于\(N\)的情况下随便填。
  2. \(S\)的长度小于\(2K\),那么前缀和后缀会互相重叠,你需要保证它们不会互相冲突,也就是仍旧满足前后缀都是\(M\)。而且,你也没有可以自由地填进去的数字了。

做法

对于上文提到的情况,可以分别实现:

  1. 我们枚举当前这个串/数字的长度,假如它的总长度小于\(N\)的总长度,那么它一定小于\(N\),中间的空当可以随便填。假如它的总长度等于\(N\)的长度,那么我们枚举某一位,在这一位前,所有的数字都和\(N\)中的一样,这一位的数字比\(N\)的这一位小了,那么后面的就随便填。特别地,有可能这一位在前\(K\)个数字中出现过了,那么中间的所有数位都随便填,或者,中间所有数位都填\(0\)时,当前的数字仍旧比\(N\)大,那么就没有合法方案。
  2. 同样的,枚举当前串/数字的长度,满足前后缀重叠部分相同这一条件需要快速判断,可以使用Z或者KMP等字符串匹配方法快速计算。

程序

做法,使用Z匹配前后缀。

#include<bits/stdc++.h>
using namespace std; typedef long long ll;
const int mod=1000000007; char s[1000005];//s表示题目中的数字N
char t[1000005];//t表示题目中的数字M
int n,m;//n, m分别表示题目中的N, M的长度
ll pw[1000005],ans;//pw[i]表示10的i次方对mod取模后的大小,ans表示最终答案 bool check(int emp){//check表示中间空出了emp个填0的数位的时候,前后缀是M的数字是否小于等于N,emp<0时,表示前后缀的M重叠了几个位置
char *r=new char[n+1];
memset(r,'0',n+1);
memcpy(r+1+n-(m+emp+m),t+1,m);
memcpy(r+1+n-m,t+1,m);//构造一个前后缀为M的数字,长度小于N时高位补零
bool fl=false,va=true;
for(int i=1;i<=n;i++){
if(r[i]<s[i])fl=true;
if(r[i]>s[i]&&!fl)va=false;
}//判断大小关系(数学意义)
delete[] r;
return va;
} int main(){ ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0); pw[0]=1;
for(int i=1;i<=1000000;i++)pw[i]=pw[i-1]*10%mod;//预处理
cin>>s+1;
n=strlen(s+1);
cin>>t+1;
m=strlen(t+1);
if(check(-m))ans++;//单个M作为数字,这里其实可能会出锅,但数据中没有
int *z=new int[m+1],l=1,r=1;
z[1]=m;
for(int i=2;i<=m;i++){
z[i]=0;
if(i>r){
l=i;r=i-1;
while(r<m&&t[r+1]==t[z[i]+1])r++,z[i]++;
}else{
if(i+z[i-l+1]<=r){
z[i]=z[i-l+1];
}else{
l=i;
z[i]=r-i+1;
while(r<m&&t[r+1]==t[z[i]+1])r++,z[i]++;
}
}
if(i+z[i]-1==m){
if(m+m-z[i]<n||(m+m-z[i]==n&&check(-z[i])))ans++;
}
}
delete[] z;//Z算法
if(m+m<n||(m+m==n&&check(0)))ans++;//计算有数字形如M+M时是否合法
for(int i=1;m+i+m<n;i++){//枚举空出了i个数字时
ans=(ans+pw[i])%mod;
}
if(m+m<n&&check(n-m-m)){
int emp=n-m-m;
bool pref=false,suff=true,suf=false;//pref表示前K个数字是否已经比N小了,这样可以随便填,suff表示M是否小于等于N的K个数字,是就可以让中间的数字全部等于N对应数位
for(int i=1;i<=m;i++){
if(s[i]>t[i])pref=true;
if(s[i+n-m]>t[i])suf=true;
if(s[i+n-m]<t[i]&&!suf)suff=false;
}
if(pref)ans=(ans+pw[emp])%mod;//加上中间任意填的方案
else{
ans=(ans+suff)%mod;//加上suff的方案
for(int i=m+1;i<=n-m;i++){
ans=(ans+pw[n-m-i]*(s[i]-'0'))%mod;//加上当前位前面的数字和N相同,当前位小于N对应数位,后面随便填的方案
}
}
}
cout<<ans%mod<<endl; return 0;
}

CSAcademy Prefix Suffix Counting 题解的更多相关文章

  1. mybatis之<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=""></trim>的含义

    转自:http://blog.csdn.net/qq_33054511/article/details/70490046   <trim prefix="" suffix=& ...

  2. mybatis之<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=""></trim>

    1.<trim prefix="" suffix="" suffixOverrides="" prefixOverrides=&quo ...

  3. [USACO17JAN]Promotion Counting 题解

    前言 巨佬说:要有线段树,结果蒟蒻打了一棵树状数组... 想想啊,奶牛都开公司当老板了,我还在这里码代码,太失败了. 话说奶牛开个公司老板不应该是FarmerJohn吗? 题解 刚看到这道题的时候竟然 ...

  4. POJ 2386 Lake Counting 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=2386 <挑战程序设计竞赛>习题 题目描述Description Due to recent rains, water has ...

  5. CF1106A Lunar New Year and Cross Counting 题解

    Content 试求出在一个 \(n\times n\) 的地图 \(M\) 中,满足 \(1\leqslant i,j\leqslant n\) 且 \(M_{i,j}=M_{i+1,j+1}=M_ ...

  6. [LeetCode] Prefix and Suffix Search 前后缀搜索

    Given many words, words[i] has weight i. Design a class WordFilter that supports one function, WordF ...

  7. [Swift]LeetCode745. 前缀和后缀搜索 | Prefix and Suffix Search

    Given many words, words[i] has weight i. Design a class WordFilter that supports one function, WordF ...

  8. 【leetcode】745. Prefix and Suffix Search

    题目如下: Given many words, words[i] has weight i. Design a class WordFilter that supports one function, ...

  9. AtCoder Grand Contest 040 简要题解

    从这里开始 比赛目录 A < B < E < D < C = F,心情简单.jpg. Problem A >< 把峰谷都设成 0. Code #include &l ...

随机推荐

  1. C#中使用protobuf-net进行序列化

    前一篇文章我们看到使用Google.Protobuf有诸多不便(参考<如何在C#中使用Google.Protobuf工具>),这次我们来看看另一个工具的使用体验. 相关资料.链接: git ...

  2. 一次奇怪的的bug排查过程

    公司对底层基础库进行了重构,线上稳定跑了几天,在查看订单系统的log时,有几条error信息非常的奇怪, orderID:80320180 statemachine error: no event [ ...

  3. SimpleNVR安防监控RTSP/FLV/HLS直播流服务如何分权限添加用户指定通道观看

    背景分析 随着SimpleNVR的用户越来越多,很多客户反馈给了我们很宝贵的简易以及用户体验.在此非常感谢大家对我们的支持.其中很多客户不想把所有的视频直播展现出来,想分权限添加新用户,指定通道让其观 ...

  4. 【2020五校联考NOIP #7】道路扩建

    题面传送门 题意: 给出一张 \(n\) 个点 \(m\) 条边的无向图 \(G\),第 \(i\) 条边连接 \(u_i,v_i\) 两个点,权值为 \(w_i\). 你可以进行以下操作一次: 选择 ...

  5. 模版 动态 dp

    模版 动态 dp 终于来写这个东西了.. LG 模版:给定 n 个点的数,点有点权, $ m $ 次修改点权,求修改完后这个树的最大独立集大小. 我们先来考虑朴素的最大独立集的 dp \[dp[u][ ...

  6. Docker Alpine Dockerfile 安装nginx,最小镜像

    Docker Alpine Dockerfile 安装nginx,最小镜像 FROM alpine MAINTAINER will ## 将alpine-linux:apk的安装源改为国内镜像 RUN ...

  7. Oracle-like 多条件过滤以及and or用法

    1.select * from  file  where DOC_SUBJECT  not like '%测试%' and (DOC_STATUS like '待审' or DOC_STATUS li ...

  8. 深度探讨 PHP 之性能

    1.缘起 关于PHP,很多人的直观感觉是PHP是一种灵活的脚本语言,库类丰富,使用简单,安全,非常适合WEB开发,但性能低下.PHP的性能是否真的就 如同大家的感觉一样的差呢?本文就是围绕这么一个话题 ...

  9. c#年份筛选

    年份: <script type="text/javascript" src="http://www.shicishu.com/down/WdatePicker.j ...

  10. Hbase(一)【入门安装及高可用】

    目录 一.Zookeeper正常部署 二.Hadoop正常部署 三.Hbase部署 1.下载 2.解压 3.相关配置 4.分发文件 5.启动.关闭 6.验证 四.HMaster的高可用 一.Zooke ...