一、题目

点此看题

二、解法

今天不知道为什么手感这么好,写一发完全没调就过掉了。

我感觉这种多组询问的字符串题是很难的,经常没有什么思路。我先考虑了一下能不能像 区间本质不同的子串个数 这样直接离线,但我想了很久发现不行的。

正确的做法是很天马行空的,我们 考虑预处理出 \(s\) 的所有子串在 \(t\) 中有没有出现 ,枚举是不可能枚举的,要把他们压在一起快速的处理。设 \(R[i]\) 为 \([i,R[i]]\) 在 \(t\) 中出现过,那么对于比 \(R[i]\) 小的右端点是一定出现过的,比 \(R[i]\) 大的右端点是没有出现过的。

\(R[i]\) 用后缀自动机可以快速处理,因为 \([i,R[i]]\) 是在 \(t\) 中出现过的,\([i+1,R[i]]\) 也是在 \(t\) 中出现过的,那么 \(R[i+1]\geq R[i]\),所以说我们可以暴力跳转移,当发现长度不适应后缀自动机上的这个点时,就可以跳后缀树上的父亲。不难发现时间复杂度是 \(O(n)\) 的。

知道了 \(R[i]\) 之后,询问 \((l,r)\) 的答案很容易写出来:

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

这个式子乍看上去没有办法优化,但别忘了我们还有一个法宝:离线 。如果你觉得里面的 \(\min\) 特别恶心那么我们可以分类讨论来去掉这个 \(\min\) :

  • \(R[i]\leq r\),那么里面的柿子就变成了:\(R[i]-i+1\)
  • \(R[i]>r\),那么里面的柿子就变成了:\(r-i+1\)

拆掉 \(\min\) 之后问题变成了二维偏序之类的东西,解决他的固定套路就是 排序降维 。那么我们把 \(R[i],r\) 都从小到大排序,然后维护两颗线段树,一颗维护 \(-i\) 的最大值,一颗维护 \(R[i]-i+1\) 就可以了。

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

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int M = 200005;
const int inf = -1e9;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,k,cnt,last,R[M],ans[M];char s[M],t[M];
int mx[2][4*M];
struct node
{
int fa,len,ch[2];
}a[2*M];
struct reg//regret
{
int l,r,id;
bool operator < (const reg &R) const
{
return r<R.r;
}
}b[M],q[M];
void add(int c)
{
int p=last,np=last=++cnt;
a[np].len=a[p].len;
for(;p && !a[p].ch[c];p=a[p].fa) a[p].ch[c]=np;
if(!p) a[np].fa=1;
else
{
int q=a[p].ch[c];
if(a[p].len+1==a[q].len) a[np].fa=q;
else
{
int nq=++cnt;a[nq]=a[q];
a[nq].len=a[p].len+1;
a[np].fa=a[q].fa=nq;
for(;p && a[p].ch[c]==q;p=a[p].fa) a[p].ch[c]=nq;
}
}
}
void ins(int i,int l,int r,int id,int v,int f)
{
if(l==r)
{
mx[f][i]=v;
return ;
}
int mid=(l+r)>>1;
if(mid>=id) ins(i<<1,l,mid,id,v,f);
else ins(i<<1|1,mid+1,r,id,v,f);
mx[f][i]=max(mx[f][i<<1],mx[f][i<<1|1]);
}
int ask(int i,int l,int r,int L,int R,int f)
{
if(L>r || l>R) return inf;
if(L<=l && r<=R) return mx[f][i];
int mid=(l+r)>>1;
return max(ask(i<<1,l,mid,L,R,f),ask(i<<1|1,mid+1,r,L,R,f));
}
signed main()
{
scanf("%s %s",s+1,t+1);
n=strlen(s+1);m=strlen(t+1);
cnt=last=1;//attention
for(int i=1;i<=m;i++)
add(t[i]-'a');
for(int i=1,p=1;i<=n;i++)
{
int r=min(i-1,R[i-1]);
if(r==i-1) p=1;
while(p!=1 && a[a[p].fa].len>r-i+1) p=a[p].fa;
while(r<n && a[p].ch[s[r+1]-'a'])
{
r++;
p=a[p].ch[s[r]-'a'];
}
R[i]=r;
b[i]=reg{i,r,0};
}
sort(b+1,b+1+n);
k=read();
for(int i=1;i<=k;i++)
{
int l=read(),r=read();
q[i]=reg{l,r,i};
}
sort(q+1,q+1+k);
memset(mx,-0x3f,sizeof mx);
for(int i=1;i<=n;i++)
ins(1,1,n,i,-i,0);
for(int i=1,j=1;i<=k;i++)
{
int l=q[i].l,r=q[i].r,id=q[i].id;
while(j<=n && b[j].r<=r)
{
ins(1,1,n,b[j].l,inf,0);
ins(1,1,n,b[j].l,b[j].r-b[j].l+1,1);
j++;
}
ans[id]=max(ask(1,1,n,l,r,1),r+ask(1,1,n,l,r,0)+1);
ans[id]=max(0,ans[id]);
}
for(int i=1;i<=k;i++)
printf("%d\n",ans[i]);
}

[BJOI2020] 封印的更多相关文章

  1. 题解 洛谷 P6640 【[BJOI2020] 封印】

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

  2. BZOJ2322: [BeiJing2011]梦想封印

    Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantasy Seal)的特技,需要引入如下的概念: 每一位魔法的 ...

  3. 「Poetize10」封印一击

    描述 Description Nescafe由n种元素组成(编号为1~n), 第i种元素有一个封印区间[ai,bi].当封印力度E小于ai时,该元素将获得ai的封印能量:当封印力度E在ai到bi之间时 ...

  4. 9102年了,汇总下HttpClient问题,封印一个

    如果找的是core的HttpClientFactory 出门右转. 官方写法,高并发下,TCP连接不能快速释放,导致端口占完,无法连接 Dispose 不是马上关闭tcp连接 主动关闭的一方为什么不能 ...

  5. [BZOJ 2322][BeiJing2011]梦想封印

    梦想封印 题意 原题面: Problem 2322. -- [BeiJing2011]梦想封印 2322: [BeiJing2011]梦想封印 Time Limit: 20 Sec  Memory L ...

  6. 【tyvj】P2065 「Poetize10」封印一击(贪心+线段树/差分)

    http://new.tyvj.cn/p/2065 我就不说我很sb的用线段树来维护值...... 本机自测的时候想了老半天没想出怎么维护点在所有区间被多少区间包含的方法.最后一小时才想出来线段树(果 ...

  7. 简单DP【p1934】封印

    Description 很久以前,魔界大旱,水井全部干涸,温度也越来越高.为了拯救居民,夜叉族国王龙溟希望能打破神魔之井,进入人界"窃取"水灵珠,以修复大地水脉.可是六界之间皆有封 ...

  8. 【BZOJ2322】[BeiJing2011]梦想封印 高斯消元求线性基+DFS+set

    [BZOJ2322][BeiJing2011]梦想封印 Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantas ...

  9. 【线性基】bzoj2322: [BeiJing2011]梦想封印

    线性基的思维题+图常见套路 Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantasy Seal)的特技,需要引 ...

随机推荐

  1. hdoj 5971

    Wrestling Match Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

  2. HDU 6704 K-th occurrence(主席树 + RMQ + 后缀数组)题解

    题意: 给一个串\(S\),\(length\leq 1e5\),\(Q\leq1e5\)个询问,每次询问输出和\(S_lS_{l+1}\dots S_r\)长得一模一样的第\(k\)个子串的开头位置 ...

  3. Spring(三) Spring IOC 初体验

    Web IOC 容器初体验 我们还是从大家最熟悉的 DispatcherServlet 开始,我们最先想到的还是 DispatcherServlet 的 init() 方法.我们发现在 Dispath ...

  4. 2019牛客多校第五场C generator 2(BSGS)题解

    题意: 传送门 已知递推公式\(x_i = a*x_{i - 1} + b\mod p\),\(p\)是素数,已知\(x_0,a,b,p\),给出一个\(n\)和\(v\),问你满足\(x_i = v ...

  5. XSS脚本汇总

    (1)普通的XSS JavaScript注入<SCRIPT SRC=http://***/XSS/xss.js></SCRIPT> (2)IMG标签XSS使用JavaScrip ...

  6. μC/OS-III---I笔记7---消息队列

    消息队列 任务之间仅仅靠信号量进行"沟通"是不够的,信号量可以标志事件的发生,却无法传递更多的数据,在需要任务间的数据信息传递时就绪要用到消息队列,传统我们一般在前后太系统中都是通 ...

  7. 写给程序员的机器学习入门 (十一) - 对象识别 YOLO - 识别人脸位置与是否戴口罩

    这篇将会介绍目前最流行的对象识别模型 YOLO,YOLO 的特征是快,识别速度非常快

  8. GitHub new features 2020 All In One

    GitHub new features 2020 All In One Discussions Discussions is the space for your community to have ...

  9. Flutter: random color

    import 'dart:math' as math; import 'package:flutter/material.dart'; void main() => runApp(App()); ...

  10. PAUL ADAMS ARCHITECT :阿联酋和美国富人推动英国高端房地产市场

    来自2020年前三季度的数据显示,在英国高端市场上,由国际买家担保的抵押贷款交易数量最多,阿联酋目前处于领先地位.到目前为止,在2020年完成的所有交易中,有35%来自阿联酋. PAUL ADAMS ...