正题

题目链接:https://www.luogu.com.cn/problem/P4022


题目大意

给出\(m\)个模板串。

然后\(n\)次询问给出一个串\(S\)要求找到一个最大的\(L\)使得能够将\(S\)超过\(90\%\)的部分拿出来分后每个串都是某个模板串的子串且长度不小于\(L\)。

所有输入文件长度不超过 \(1100000\) 字节。字符集为\(\{0,1\}\)


解题思路

先把模板串拿出来构一个广义SAM,然后考虑用这个对串进行匹配。

先对于每个位置求出一个\(len_i\)表示一个最长的长度使得\(i\)的后缀是某个模板串的子串。

然后考虑二分一个\(L\)后进行\(dp\)。

那么有

\[f_i=max\{f_{i-1},f_j+i-j\}(\ j\in[i-len_i,i-L)\ )
\]

因为\(i-len_i\)单调所以把\(j\)丢进单调队列里就好了。

时间复杂度\(O(n\log n)\)


code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. const int N=1200000;
  6. int n,m,cnt,f[N],q[N],ml[N];
  7. int ch[N][2],len[N],fa[N];
  8. char s[N];
  9. int Insert(int p,int c){
  10. if(ch[p][c]){
  11. int q=ch[p][c];
  12. if(len[p]+1==len[q])return q;
  13. else{
  14. int nq=++cnt;len[nq]=len[p]+1;
  15. memcpy(ch[nq],ch[q],sizeof(ch[nq]));
  16. fa[nq]=fa[q];fa[q]=nq;
  17. for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
  18. return nq;
  19. }
  20. }
  21. int np=++cnt;len[np]=len[p]+1;
  22. for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
  23. if(!p)fa[np]=1;
  24. else{
  25. int q=ch[p][c];
  26. if(len[p]+1==len[q])fa[np]=q;
  27. else{
  28. int nq=++cnt;len[nq]=len[p]+1;
  29. memcpy(ch[nq],ch[q],sizeof(ch[nq]));
  30. fa[nq]=fa[q];fa[q]=fa[np]=nq;
  31. for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
  32. }
  33. }
  34. return np;
  35. }
  36. bool check(int L,int n){
  37. int head=1,tail=0,ans=0;
  38. for(int i=1;i<=n;i++){
  39. if(i>=L){
  40. int j=i-L;
  41. while(head<=tail&&f[j]-j>f[q[tail]]-q[tail])tail--;
  42. q[++tail]=j;
  43. }
  44. while(head<=tail&&q[head]<i-ml[i])head++;
  45. f[i]=0;
  46. if(head<=tail)f[i]=f[q[head]]+i-q[head];
  47. f[i]=max(f[i],f[i-1]);
  48. ans=max(ans,f[i]);
  49. }
  50. return (ans*10>=n*9);
  51. }
  52. int main()
  53. {
  54. scanf("%d%d",&n,&m);cnt=1;
  55. for(int i=1;i<=m;i++){
  56. scanf("%s",s+1);
  57. int l=strlen(s+1),x=1;
  58. for(int j=1;j<=l;j++)
  59. x=Insert(x,s[j]-'0');
  60. }
  61. while(n--){
  62. scanf("%s",s+1);
  63. int sl=strlen(s+1),x=1,L=0;
  64. for(int i=1;i<=sl;i++){
  65. int c=s[i]-'0';
  66. while(x&&!ch[x][c])
  67. {x=fa[x];L=len[x];}
  68. if(x)x=ch[x][c],L++;
  69. else x=1,L=0;
  70. ml[i]=L;
  71. }
  72. int l=1,r=sl;
  73. while(l<=r){
  74. int mid=(l+r)>>1;
  75. if(check(mid,sl))l=mid+1;
  76. else r=mid-1;
  77. }
  78. printf("%d\n",r);
  79. }
  80. return 0;
  81. }

P4022-[CTSC2012]熟悉的文章【广义SAM,dp,单调队列】的更多相关文章

  1. Luogu4022 CTSC2012 熟悉的文章 广义SAM、二分答案、单调队列

    传送门 先将所有模板串扔进广义SAM.发现作文的\(L0\)具有单调性,即\(L0\)更小不会影响答案,所以二分答案. 假设当前二分的值为\(mid\),将当前的作文放到广义SAM上匹配. 设对于第\ ...

  2. [CTSC2012]熟悉的文章 (后缀自动机 单调队列)

    /* 首先答案显然是具有单调性的, 所以可以二分进行判断 然后当我们二分过后考虑dp来求最长匹配个数, 发现每个点能够转移的地点 肯定是一段区间, 然后这样就能够得到一个log^2算法 至于每个点的匹 ...

  3. P4022 [CTSC2012]熟悉的文章

    题目 P4022 [CTSC2012]熟悉的文章 题目大意:多个文本串,多个匹配串,我们求\(L\),\(L\)指(匹配串中\(≥L\)长度的子串出现在文本串才为"熟悉",使得匹配 ...

  4. CTSC2012 熟悉的文章 广义后缀自动机_单调队列

    没啥难的,主要是单调队列忘了咋求了QAQ... Code: #include <cstdio> #include <algorithm> #include <cstrin ...

  5. [poj3017] Cut the Sequence (DP + 单调队列优化 + 平衡树优化)

    DP + 单调队列优化 + 平衡树 好题 Description Given an integer sequence { an } of length N, you are to cut the se ...

  6. DP+单调队列 codevs 1748 瑰丽华尔兹(还不是很懂具体的代码实现)

    codevs 1748 瑰丽华尔兹 2005年NOI全国竞赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 大师 Master 题解       题目描述 Descripti ...

  7. 习题:烽火传递(DP+单调队列)

    烽火传递[题目描述]烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有n个烽火台,每个烽火台 ...

  8. (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列

    Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...

  9. 3622 假期(DP+单调队列优化)

    3622 假期 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 黄金 Gold 题目描述 Description 经过几个月辛勤的工作,FJ决定让奶牛放假.假期可以在1-N天内任意选择 ...

随机推荐

  1. C++类构造函数、拷贝构造函数、复制构造函数、复制构造函数、构造函数显示调用和隐式调用

    一. 构造函数是干什么的   class Counter   {   public:            // 类Counter的构造函数            // 特点:以类名作为函数名,无返回 ...

  2. CentOS8安装Mysql5.7

    检查是否安装mysql [root@iZ2ze8crquorxf6c7l0eluZ ~]# rpm -qa |grep mysql [root@iZ2ze8crquorxf6c7l0eluZ ~]# ...

  3. bootStrap模态框与select2合用时input不能获取焦点、模态框内部滑动,select选中跳转

    bootStrap模态框与select2合用时input不能获取焦点 在bootstrap的模态框里使用select2插件,会导致select2里的input输入框没有办法获得焦点,没有办法输入. 把 ...

  4. 简析时序数据库 InfluxDB

    时序数据基础 时序数据特点 时序数据TimeSeries是一连串随时间推移而发生变化的相关事件. 以下图的 CPU 监控数据为例,同个 IP 的相关监控数据组成了一条时序数据,不相关数据则分布在不同的 ...

  5. ubuntu中用update-alternatives进行软件多版本设置、切换,以python配置为例

    以Python2.7和Python3.5设置为例: 在系统中添加Python2.7.Python3.5的选项,默认为Python3.5 sudo update-alternatives --insta ...

  6. ROS catkin_make error Could not find a package configuration file provided by "actionlib_msgs"

    在使用ROS catkin_make编译的时候,出现类似如下错误 CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkinConfig.cma ...

  7. MySQL的几种锁机制的使用介绍

    锁 在日常的开发过程中,为了控制线程的并发肯定会用到锁机制.对于数据库而言,锁机制就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则.当然MySQL也不例外,根据不同 ...

  8. Spring依赖注入的四种方式

    首先,我们需要定义一个Bean的class类: package framework.spring; import org.springframework.beans.BeansException; i ...

  9. 用XPath定位Web页面元素时,如何快速验证XPath语句是否正确?

    在使用Selenium做Web UI自动化测试的过程中,XPath是一种定位页面元素的常用方式.然而,面对某些元素的XPath路径过于复杂,我们想快速验证拼凑的Xpath语句是否正确时,该怎么办呢?这 ...

  10. Redis核心原理与实践--字符串实现原理

    Redis是一个键值对数据库(key-value DB),下面是一个简单的Redis的命令: > SET msg "hello wolrd" 该命令将键"msg&q ...