题目链接:Cheat

  话说这道题很久以前某人就给我们考过,直到现在,我终于把这个坑填上了……

  这道题要我们把一个串\(S\)划分成若干块,每块长度不小于\(L_0\),使得能够在文章库中完全匹配的块的长度和占总长度的\(90\%\)以上。首先,答案显然是可以二分的。于是,我们就可以二分一个答案\(ans\),考虑如何\(check\)。

  很显然的一个想法就是\(dp\)。如果我们知道这个串的第\(i\)位往前最多能够走\(x_i\)位,使得\(S_{i-x_i}\)到\(S_i\)组成的串能够在文章库中匹配,那么我们就可以写出\(dp\)方程了:\begin{aligned} f_i=&\max \{ f_j+i-j \}(i-x_i \le j \le i-ans) \\ = &i+\max \{ f_i-j \}\ (i-x_i \le j \le i-ans) \end{aligned}

  当然,\(f_i=\max(f_i,f_{i-1})\)

  然后,我们就可以发现\(i-x_i\)是单调的(话说我刚开始还没有看出来),然后由于\(i-ans\)显然也是单调的,所以我们就可以弄个单调队列维护区间最大值即可。最后再判断一下总的匹配长度是否大于等于总长度的\(90\%\)即可。

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 2200010 using namespace std;
typedef long long llg; int n,m,tot,last,f[maxn>>1],L,pi[maxn>>1];
int son[maxn][2],fa[maxn],len[maxn],d[maxn>>1],ld,rd;
char s[maxn>>1]; void add(int p,int x){
int np=++tot; len[np]=len[p]+1,fa[np]=p; last=np;
for(;p && !son[p][x];p=fa[p]) son[p][x]=np;
if(!p) fa[np]=1;
else{
int q=son[p][x];
if(len[q]==len[p]+1) fa[np]=q;
else{
int nq=++tot;
memcpy(son[nq],son[q],sizeof(son[q]));
fa[nq]=fa[q]; fa[q]=fa[np]=nq; len[nq]=len[p]+1;
for(;son[p][x]==q;p=fa[p]) son[p][x]=nq;
}
}
} bool check(int x){
ld=rd=0;
for(int i=1;i<=L;i++){f[i]=f[i-1];
if(i>=x){
while(ld<rd && f[d[rd-1]]-d[rd-1]<=f[i-x]-i+x) rd--;
d[rd++]=i-x;
}
while(ld<rd && d[ld]<i-pi[i]) ld++;
if(ld<rd) f[i]=max(f[i],f[d[ld]]-d[ld]+i);
}
return f[L]*10>=9*L;
} int main(){
File("a");
scanf("%d %d",&n,&m); tot=1;
for(int i=1,l;i<=m;i++){
scanf("%s",s+1);
last=1; l=strlen(s+1);
for(int j=1;j<=l;j++) add(last,s[j]-'0');
}
for(int i=1,l,r,mid;i<=n;i++){
scanf("%s",s+1);
l=0; L=r=strlen(s+1);
for(int j=1,p=1,le=0;j<=L;j++){
while(p!=1 && !son[p][s[j]-'0']) p=fa[p],le=len[p];
if(son[p][s[j]-'0']) p=son[p][s[j]-'0'],le++; pi[j]=le;
}
while(l!=r){
mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
printf("%d\n",l);
}
return 0;
}

最新文章

  1. linux 配置ssh免密码登陆本机
  2. 01Spring_基本jia包的导入andSpring的整体架构and怎么加入日志功能
  3. Bower 手册
  4. Unity 3D学习之 Prime31 Game Center插件用法
  5. Java中的DatagramPacket与DatagramSocket的初步(转)
  6. Gitlab仓库规范实践建议
  7. 深度模拟java动态代理实现机制系类之三
  8. Eclipse下Tomcat常用设置
  9. JavaScript HTML DOM 事件
  10. sql 行转列总结
  11. 对于crontab定时任务不能自动执行的总结
  12. Oracle 安装步骤、安装中错误处理、完整卸载
  13. 复杂的xml资源
  14. si_da
  15. OpenSSL 正确安装
  16. redis(三)
  17. Linux编程 6 (查看进程 ps 及输出风格)
  18. 第八次Scrum meeting
  19. 【mybatis源码学习】mybtias一级,二级缓存
  20. sphinx 同时使用多个索引进行检索探究

热门文章

  1. SQL中distinct的用法(转载)
  2. T-SQL创建作业
  3. docx4j基本操作
  4. openstack配置域名访问
  5. EOS 的网站及资料doc
  6. python学习笔记(二十九)为什么python的多线程不能利用多核CPU
  7. ABP常见问题
  8. 程序员:统治世界or修复bug?
  9. 文件下载—SSH框架文件下载
  10. Java数据结构和算法总结-字符串相关高频面试题算法