一、题目

点此看题

二、解法

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

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

正确的做法是很天马行空的,我们 考虑预处理出 \(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. 加密后的程序在Win8中无法运行

    需要使用dotNET_Reactor 4.7以上的版本加密后才能在Win8中使用.

  2. Win10永久禁用驱动程序强制签名

    在win10下用一个命令就可以禁用驱动程序强制签名 1.禁止强制签名,以管理员的身份运行cmd 执行以下命令 bcdedit.exe /set nointegritychecks on 恢复默认验证, ...

  3. codefoeces 864B

    B. Polycarp and Letters time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  4. 洛谷p2216 多次单调队列,扫描矩阵中的最大值减去最小值最的固定大小子矩阵

    #include <iostream> #include <cstdio> #include <cstring> using namespace std; int ...

  5. 知乎 bug

    知乎 bug shit zhihu https://zhuanlan.zhihu.com/p/111809590 无法展开评论 https://unpkg.zhimg.com/@cfe/sentry- ...

  6. React Hooks vs React Class vs React Function All In One

    React Hooks vs React Class vs React Function All In One React Component Types React Hooks Component ...

  7. Expose Loader & shit jquery

    Expose Loader webpack https://github.com/xgqfrms/FEIQA/issues/31#issuecomment-418255126 require(&quo ...

  8. macOS finder show hidden files

    macOS finder show hidden files 显示 MacOS 上的隐藏文件和文件夹 https://zh.wikihow.com/显示Mac-OS-X上的隐藏文件和文件夹 $ def ...

  9. macOS open url from terminal

    macOS open url from terminal open URL && start terminal bash open url in chrome open chrome ...

  10. HTML5 & custom element & template

    HTML5 & custom element & template template https://codepen.io/xgqfrms/pen/eYYExvp https://cs ...