[BJOI2020] 封印
一、题目
二、解法
今天不知道为什么手感这么好,写一发完全没调就过掉了。
我感觉这种多组询问的字符串题是很难的,经常没有什么思路。我先考虑了一下能不能像 区间本质不同的子串个数 这样直接离线,但我想了很久发现不行的。
正确的做法是很天马行空的,我们 考虑预处理出 \(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)\) 的答案很容易写出来:
\]
这个式子乍看上去没有办法优化,但别忘了我们还有一个法宝:离线 。如果你觉得里面的 \(\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] 封印的更多相关文章
- 题解 洛谷 P6640 【[BJOI2020] 封印】
设\(lenth_i\)为\(s\)在\(i\)位置的前缀的后缀为\(t\)的一个子串的最长长度,即为从\(i\)位置开始往前和\(t\)的最长公共子串长度.其可以通过对\(t\)建后缀自动机,然后让 ...
- BZOJ2322: [BeiJing2011]梦想封印
Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantasy Seal)的特技,需要引入如下的概念: 每一位魔法的 ...
- 「Poetize10」封印一击
描述 Description Nescafe由n种元素组成(编号为1~n), 第i种元素有一个封印区间[ai,bi].当封印力度E小于ai时,该元素将获得ai的封印能量:当封印力度E在ai到bi之间时 ...
- 9102年了,汇总下HttpClient问题,封印一个
如果找的是core的HttpClientFactory 出门右转. 官方写法,高并发下,TCP连接不能快速释放,导致端口占完,无法连接 Dispose 不是马上关闭tcp连接 主动关闭的一方为什么不能 ...
- [BZOJ 2322][BeiJing2011]梦想封印
梦想封印 题意 原题面: Problem 2322. -- [BeiJing2011]梦想封印 2322: [BeiJing2011]梦想封印 Time Limit: 20 Sec Memory L ...
- 【tyvj】P2065 「Poetize10」封印一击(贪心+线段树/差分)
http://new.tyvj.cn/p/2065 我就不说我很sb的用线段树来维护值...... 本机自测的时候想了老半天没想出怎么维护点在所有区间被多少区间包含的方法.最后一小时才想出来线段树(果 ...
- 简单DP【p1934】封印
Description 很久以前,魔界大旱,水井全部干涸,温度也越来越高.为了拯救居民,夜叉族国王龙溟希望能打破神魔之井,进入人界"窃取"水灵珠,以修复大地水脉.可是六界之间皆有封 ...
- 【BZOJ2322】[BeiJing2011]梦想封印 高斯消元求线性基+DFS+set
[BZOJ2322][BeiJing2011]梦想封印 Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantas ...
- 【线性基】bzoj2322: [BeiJing2011]梦想封印
线性基的思维题+图常见套路 Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantasy Seal)的特技,需要引 ...
随机推荐
- [Golang]-6 超时处理、非阻塞通道操作、通道的关闭和遍历
目录 超时处理 非阻塞通道操作 通道的关闭 通道遍历 超时处理 超时 对于一个连接外部资源,或者其它一些需要花费执行时间的操作的程序而言是很重要的. 得益于通道和 select,在 Go中实现超时操作 ...
- Hexo-使用阿里iconfont图标
Hexo-使用阿里iconfont图标 因为使用hexo搭建的博客中,大家并不懂都有什么图标,fa fa-xx就懵了,不知道都有什么. 首先,fa fa-xxx中的图标可以在 图标库 中寻找. (上面 ...
- JavaScript基本包装类介绍
为了便于操作基本类型值,ECMAScript 提供了 3 个特殊的引用类型:Boolean.Number和 String.这些类型与其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为.实际上 ...
- RT-Thread学习笔记1-启动顺序与线程创建
目录 1. 启动顺序 2. 堆范围 3. 线程创建 3.1 线程代码(入口函数) 3.2 线程控制块 3.3 线程栈 4. 系统滴答时钟 5. GPIO驱动架构操作IO 6. 线程优先级 & ...
- ossutilmac64
ossutilmac64 ossutil是以命令行方式管理OSS数据的工具,提供方便.简洁.丰富的存储空间(Bucket)和文件(Object)管理命令,支持Windows.Linux. Mac平台. ...
- javascript module system all in one
javascript module system all in one AMD & CMD https://github.com/amdjs/amdjs-api/wiki/AMD http:/ ...
- How to enable HTTPS for local development in macOS using Chrome
How to enable HTTPS for local development in macOS using Chrome HTTPS, macOS, Chrome local HTTPS htt ...
- Internationalization API & ECMA-402
Internationalization API & ECMA-402 i18n https://caniuse.com/?search=Internationalization API In ...
- USDN代币多少钱?USDN有什么用?
加密货币走向主流人群的采用有很多障碍,比如监管.交易所黑客事件等,但最明显的障碍还是它们极端的价格波动.这从加密货币的整个历史长度来看都是如此.一个货币要正常运转,比如成为有效的交换媒介.记账单位以及 ...
- 华盛顿邮报专访:SPC能否再掀起币圈新浪潮?
近日,美国知名媒体华盛顿邮报对话NGK灵石团队技术副总裁Daphne Patel女士,对话主题为"SPC能否再掀起币圈新浪潮".此次对话以问答的形式展开,将SPC的最新情况呈现在你 ...