设\(lenth_i\)为\(s\)在\(i\)位置的前缀的后缀为\(t\)的一个子串的最长长度,即为从\(i\)位置开始往前和\(t\)的最长公共子串长度。其可以通过对\(t\)建后缀自动机,然后让\(s\)在自动机上匹配来求出。

求出\(lenth_i\)后,对于区间\([l,r]\)的一个询问,其答案即为:

\[ \max_{i=l}^r \lbrace\ \min(lenth_i,i-l+1)\ \rbrace
\]

发现内层的\(\min\)不好处理,考虑将其去掉:

当\(lenth_i \leqslant i-l+1\)时,其值为\(lenth_i\),转化得\(i-lenth_i+1 \geqslant l\),发现\(i-lenth_i+1\)的值是单调不降的,因为每到下一个位置,\(i\)都会加一,而\(lenth_i\)可能加一,可能清零,所以该值是单调不降的。

那么对于区间\([l,r]\),一定存在一个位置\(pos\),满足所有\(i \geqslant pos\),都有\(i-lenth_i+1 \geqslant l\)。那么在区间\([pos,r]\)中,\(\min\)取到了\(lenth_i\),在区间\([l,pos-1]\)中,\(\min\)取到了\(i-l+1\)。

\(pos\)可以通过二分求得,然后答案即为区间\([pos,r]\)内\(lenth_i\)的最大值和\(pos-l\)取\(\max\)。

\(code:\)

#include<bits/stdc++.h>
#define maxn 400010
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int l1,l2,q,root=1,las=1,tot=1;
int len[maxn],fa[maxn],ch[maxn][2],lenth[maxn],f[maxn][25],lg[maxn];
char s[maxn],t[maxn];
void insert(int c)
{
int p=las,np=las=++tot;
len[np]=len[p]+1;
while(p&&!ch[p][c]) ch[p][c]=np,p=fa[p];
if(!p) fa[np]=root;
else
{
int q=ch[p][c];
if(len[q]==len[p]+1) fa[np]=q;
else
{
int nq=++tot;
ch[nq][0]=ch[q][0],ch[nq][1]=ch[q][1];
len[nq]=len[p]+1,fa[nq]=fa[q],fa[q]=fa[np]=nq;
while(ch[p][c]==q) ch[p][c]=nq,p=fa[p];
}
}
}
void init()
{
lg[0]=-1;
for(int i=1;i<=l1;++i) lg[i]=lg[i>>1]+1;
for(int i=1;i<=l1;++i) f[i][0]=lenth[i];
for(int j=1;j<=20;++j)
for(int i=1;i+(1<<j)-1<=l1;++i)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int query(int l,int r)
{
if(l>r) return 0;
int len=lg[r-l+1];
return max(f[l][len],f[r-(1<<len)+1][len]);
}
int find(int l,int r)
{
int pos=r+1,L=l;
while(l<=r)
{
int mid=(l+r)>>1;
if(mid-lenth[mid]+1>=L) pos=mid,r=mid-1;
else l=mid+1;
}
return pos;
}
void work()
{
int p=root;
for(int i=1;i<=l1;++i)
{
int c=s[i]-'a';
if(ch[p][c]) lenth[i]=lenth[i-1]+1,p=ch[p][c];
else
{
while(p&&!ch[p][c]) p=fa[p];
if(!p) p=root;
else lenth[i]=len[p]+1,p=ch[p][c];
}
}
}
int main()
{
scanf("%s%s",s+1,t+1);
l1=strlen(s+1),l2=strlen(t+1);
for(int i=1;i<=l2;++i) insert(t[i]-'a');
work(),init(),read(q);
while(q--)
{
int l,r,pos;
read(l),read(r),pos=find(l,r);
printf("%d\n",max(query(pos,r),pos-l));
}
return 0;
}

题解 洛谷 P6640 【[BJOI2020] 封印】的更多相关文章

  1. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  2. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  3. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  4. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  5. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

  6. 题解-洛谷P4859 已经没有什么好害怕的了

    洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...

  7. 题解-洛谷P5217 贫穷

    洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...

  8. 题解 洛谷 P2010 【回文日期】

    By:Soroak 洛谷博客 知识点:模拟+暴力枚举 思路:题目中有提到闰年然后很多人就认为,闰年是需要判断的其实,含有2月29号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...

  9. 题解 洛谷P2158 【[SDOI2008]仪仗队】

    本文搬自本人洛谷博客 题目 本文进行了一定的更新 优化了 Markdown 中 Latex 语句的运用,加强了可读性 补充了"我们仍不曾知晓得 消失的 性质5 ",加强了推导的严谨 ...

随机推荐

  1. vipkid 面试经历

    今天下午去了位于钟鼓楼旁边的 vipkid 研发部进行了面试,面试过程中的回答只能说一般,面试官问的问题大概分为: 实际项目的设计问题 mysql的使用优化问题 多线程与锁的问题 JVM底层原理的问题 ...

  2. windows 64位上安装mysql 5.7版本

    下载的mysql不是安装exe的软件,而是在windows上编译好的二进制mysql软件 下载安装之后配置环境变量:将目录D:\Program Files\mysql-5.7.18-winx64\my ...

  3. Laravel 如何在blade文件中使用Vue组件

    Laravel 如何在blade文件中使用Vue组件 1. 安装laravel/ui依赖包 composer require laravel/ui 2.生成vue基本脚手架 php artisan u ...

  4. 3分钟理解NMS非极大值抑制

    1. NMS被广泛用到目标检测技术中,正如字面意思,抑制那些分数低的目标,使最终框的位置更准: 2. 假如图片上实际有10张人脸,但目标检测过程中,检测到有30个框的位置,并且模型都认为它们是人脸,造 ...

  5. 洛谷 P2212 【[USACO14MAR]Watering the Fields S】

    一道最小生成树模板题,这里用的Kruskal算法,把每两点就加一条边,跑一遍最小生成树即可. #include <bits/stdc++.h> using namespace std; s ...

  6. Java 从入门到进阶之路(二十八)

    在之前的文章我们都是通过 Java 在内存中应用,本章开始我们来看一下 Java 在系统文件(硬盘)上的操作. 系统文件就是我们电脑中的文件,简单来说就是像 Windows 系统中 C D E 等各类 ...

  7. 修改git指令alias

    修改git指令alias 嫌打git add, git push 太麻烦,可以修改bash里的 alias,改成'ga','gp'这样的短命令 打开 Git Bash, 创建修改.bashrc文件. ...

  8. Java编程资料

    Java相关免费编程书籍推荐(都是PDF版) 编程进阶 2017年9月11日 IDE IntelliJ IDEA 简体中文专题教程 https://github.com/judasn/IntelliJ ...

  9. (私人收藏)Linux命令大全(修正版)

    Linux命令大全(修正版) https://pan.baidu.com/s/1tPTv1PzCelBC_Eq-ASAOBg1yp3 文件传输 bye ftp ftpcount ftpshut ftp ...

  10. Java1.7的HashMap源码分析-面试必备技能

    HashMap是现在用的最多的map,HashMap的源码可以说是面试必备技能,今天我们试着分析一下jdk1.7下的源码. 先说结论:数组加链表 一.先看整体的数据结构 首先我们注意到数据是存放在一个 ...