正题

题目链接: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

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1200000;
int n,m,cnt,f[N],q[N],ml[N];
int ch[N][2],len[N],fa[N];
char s[N];
int Insert(int p,int c){
if(ch[p][c]){
int q=ch[p][c];
if(len[p]+1==len[q])return q;
else{
int nq=++cnt;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[nq]=fa[q];fa[q]=nq;
for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
return nq;
}
}
int np=++cnt;len[np]=len[p]+1;
for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
if(!p)fa[np]=1;
else{
int q=ch[p][c];
if(len[p]+1==len[q])fa[np]=q;
else{
int nq=++cnt;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[nq]=fa[q];fa[q]=fa[np]=nq;
for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq;
}
}
return np;
}
bool check(int L,int n){
int head=1,tail=0,ans=0;
for(int i=1;i<=n;i++){
if(i>=L){
int j=i-L;
while(head<=tail&&f[j]-j>f[q[tail]]-q[tail])tail--;
q[++tail]=j;
}
while(head<=tail&&q[head]<i-ml[i])head++;
f[i]=0;
if(head<=tail)f[i]=f[q[head]]+i-q[head];
f[i]=max(f[i],f[i-1]);
ans=max(ans,f[i]);
}
return (ans*10>=n*9);
}
int main()
{
scanf("%d%d",&n,&m);cnt=1;
for(int i=1;i<=m;i++){
scanf("%s",s+1);
int l=strlen(s+1),x=1;
for(int j=1;j<=l;j++)
x=Insert(x,s[j]-'0');
}
while(n--){
scanf("%s",s+1);
int sl=strlen(s+1),x=1,L=0;
for(int i=1;i<=sl;i++){
int c=s[i]-'0';
while(x&&!ch[x][c])
{x=fa[x];L=len[x];}
if(x)x=ch[x][c],L++;
else x=1,L=0;
ml[i]=L;
}
int l=1,r=sl;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid,sl))l=mid+1;
else r=mid-1;
}
printf("%d\n",r);
}
return 0;
}

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. Docker创建Nexus

    docker-compose.yml 注意为/usr/local/docker/nexus/data授权读写权限! version: '3.1' services: nexus: restart: a ...

  2. C#多线程---Event类实现线程同步

    一.简介 我们使用类(.net Framework中的类,如 AutoResetEvent, Semaphore类等)的方法来实现线程同步的时候,其实内部是调用操作系统的内核对象来实现的线程同步. S ...

  3. C++ 子类调用父类的方法,静态方法的调用

    #include <iostream> class  A { public: A(); ~ A(); virtualvoid say() { std::cout << &quo ...

  4. Redis3.0.0集群一键脚本 -by古斌

    下载地址(以交由码云托管): https://gitee.com/gubin0412/Redis3.0.0 赋予脚本执行权限  chmod +x redis-gubin.sh 使用 ./redis-g ...

  5. 网络视频m3u8解密及ts文件合并

    网络视频m3u8解密及ts文件合并 参考了两篇博客: https://blog.csdn.net/weixin_41624645/article/details/95939510 https://bl ...

  6. servlet中servletContext的五大作用(一)

    获取web的上下文路径 获取全局的参数 作为域对象使用 请求转发 读取web项目的资源文件 package day10.about_servletcontext.get_path; /** * 首先区 ...

  7. Servlet学习之复习

    Servlet的注册与运行(Servlet程序通常需要存储在<web应用程序目录>\WEB-INF\classes\目录中) 1.注册Servlet:在web.xml文件中,一个<s ...

  8. 跨域@RequestBody@RequestParam 和JSON.stringify

  9. 虚拟数字存储表——SQLServer2012可高用

    窗口函数之虚拟数字辅助表 数字辅助表是一个整数序列,可以用它来完成多种不同的查询任务.数字表有很多任务,如生成日期和时间值序列,及分裂值列表.通常,建议在数据库中保存这样一个永久表,并填充尽可能多的数 ...

  10. K8S集群架构的组件组成

    1.Master--主控节点 (1)apiserver:集群统一入口,以restful的方式,交给etcd存储 (2)scheduler:节点调度,选择node节点应用部署 (3)controller ...