换markdown写了。。

题意:

给你一个1e5的字符串,1e5组询问,求\([l_1,r_1]\)的所有子串与\([l_2,r_2]\)的lcp

思路:

首先可以发现答案是具有单调性的,我们考虑二分答案,二分的范围显然为\([0,min(r_2-l_2+1,r_1-l_1+1)]\)
对于二分到的字符串长度mid,可以知道它的开头一定在\([l_1,r_1-mid+1]\)中,这样满足了限定条件
于是我们可以通过检查\([l_1,r_1-mid+1]\)中是否有个值p,使得\(lcp(rk[p],rk[l_2]) \geq mid\)即可判断答案

法一:

由\(lcp(i,j)=min(height[k]),i+1\leq k \leq j\)(i,j为排名)可知
为了使\(lcp(rk[p],rk[l2])\)尽量满足条件,rk[p]一定是目标区间内,\(rk[l_2]\)的前驱或后继
这样我们可以对(i,rk[i])建主席树,每次check查询\([l_1,r_1-mid+1]\)里\(rk[l_2]\)的前驱后继
但是问题来了,主席树查询前驱后继会退化。。(我乱讲的,可能是我不会写)
虽然在bzoj上跑了16s过了,但是这显然不优秀

update:退化的问题已经解决了:权值线段树剪枝的误解--以HDU6703为例

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) using namespace std;typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 2e5+100;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);int n,m;
char s[maxn];
int sa[maxn],rk[maxn],height[maxn];
int y[maxn],x[maxn],c[maxn];
void getSa(){for(int i=1;i<=n;i++)++c[x[i]=s[i]];for(int i=2;i<=m;i++)c[i]+=c[i-1];for(int i=n;i>=1;i--)sa[c[x[i]]--]=i;for(int k=1;k<=n;k<<=1){int num = 0;for(int i=n-k+1;i<=n;i++)y[++num]=i;for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;for(int i=1;i<=m;i++)c[i]=0;for(int i=1;i<=n;i++)++c[x[i]];for(int i=2;i<=m;i++)c[i]+=c[i-1];for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0;swap(x,y);x[sa[1]]=1;num=1;for(int i=2;i<=n;i++){x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;}if(num==n)break;m=num;}
}
void getHeight(){int k=0;for(int i=1; i<=n; ++i)rk[sa[i]]=i;for(int i=1; i<=n; ++i){if(rk[i]==1) continue;if(k)--k;int j=sa[rk[i]-1];while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k])++k;height[rk[i]]=k;}
}
int d[maxn][26];
void init(){for(int i = 1; i <= n; i++) d[i][0]=height[i];for(int j = 1; (1<<j) <= n; j++){for(int i = 1; i + (1<<j) - 1 <= n; i++){d[i][j] = min(d[i][j-1], d[i + (1<<(j-1))][j-1]);}}
}
int rmq(int l, int r){if(l>r)return -1;int k = 0;while((1<<(k+1)) <= r-l+1)k++;return min(d[l][k], d[r-(1<<k)+1][k]);
}
int q;int tot,root[maxn];
int dat[maxn*40],ls[maxn*40],rs[maxn*40];
int insert(int now, int l, int r, int x, int val){int p = ++tot;dat[p]=dat[now];ls[p]=ls[now];rs[p]=rs[now];if(l==r){dat[p]+=val;return p;}int mid = (l+r)>>1;if(x<=mid)ls[p]=insert(ls[now],l,mid,x,val);else rs[p]=insert(rs[now],mid+1,r,x,val);dat[p]=dat[ls[p]]+dat[rs[p]];return p;
}
int askmx(int x, int y, int l, int r, int k){//return rk|-1int sumr = dat[rs[y]]-dat[rs[x]];int mid = (l+r)>>1;if(dat[y]-dat[x]==0)return -1;if(l==r) return l;if(mid<k){int lRes = askmx(rs[x],rs[y],mid+1,r,k);if(lRes==-1)lRes=askmx(ls[x],ls[y],l,mid,k);return lRes;}else return askmx(ls[x],ls[y],l,mid,k);}
int askmi(int x, int y, int l, int r, int k){int suml = dat[ls[y]]-dat[ls[x]];int mid = (l+r)>>1;if(dat[y]-dat[x]==0)return -1;if(l==r)return l;if(mid>k){int rRes=askmi(ls[x],ls[y],l,mid,k);if(rRes==-1)rRes=askmi(rs[x],rs[y],mid+1,r,k);return rRes;}else return askmi(rs[x],rs[y],mid+1,r,k);
}
bool ck(int x, int l1, int r1, int l2, int r2){int L = askmx(root[l1-1],root[r1-x+1],1,n,rk[l2]);int R = askmi(root[l1-1],root[r1-x+1],1,n,rk[l2]);if(L!=-1)L=rmq(L+1,rk[l2]);if(R!=-1)R=rmq(rk[l2]+1,R);return (L>=x||R>=x);
}
int main() {tot=0;scanf("%d %d", &n, &q);scanf("%s",s+1);m=122;n=strlen(s+1);getSa();getHeight();init();for(int i = 1; i <= n; i++){root[i]=insert(root[i-1],1,n,rk[i],1);}init();while(q--){int l1,r1,l2,r2;scanf("%d %d %d %d", &l1, &r1,&l2, &r2);int ans = 0;if(l2>=l1&&l2<=r1)ans=min(r2-l2+1,r1-l2+1);int l = 0, r = min(r1-l1+1,r2-l2+1);int res = 0;while(l<=r){int mid = (l+r)>>1;if(ck(mid,l1,r1,l2,r2)){l=mid+1;res=mid;}else r=mid-1;}ans=max(ans,res);printf("%d\n",ans);}return 0;
}
/*
8 1
ththhtht
1 6 7 885 292 31 259
79 299 5 2328 10
aababbab
1 1 1 1
1 2 4 5
1 5 4 5
2 3 4 5
1 5 2 5
1 6 7 8
3 6 1 7
4 4 3 8
1 5 1 8
2 4 5 8*/

法二:

既然\(lcp(i,j)\)对于i向左以及j向右都是单调不增的,我们可以二分出rk的左右边界L以及R,使得\(lcp(i,rk[l_2])\geq mid\)
然后我们对于(i,sa[i])建可持久化线段树,查询区间\((L+1,rk[l2])\)中是否有坐标在\([l_1,r_1-mid+1]\)中
这样复杂度是完美的\(O(nlog^2n)\)

代码:

我好懒,没写代码

转载于:https://www.cnblogs.com/wrjlinkkkkkk/p/11506948.html

BZOJ 4556(后缀数组+主席树求前驱后继+二分||后缀数组+二分+可持久化线段树)相关推荐

  1. 【用学校抄作业带你走进可持久化线段树(主席树)】可持久化线段树概念+全套模板+例题入门:[福利]可持久化线段树)

    我似乎很少写这种算法博客 可持久化线段树概念 概念介绍(类比帮助理解) 简单分析一下时间和空间复杂度(内容池) 模板 结构体变量 建树模板 单点修改模板 单点查询模板 区间修改模板(pushup) 区 ...

  2. 解题报告:P3834 【模板】可持久化线段树 2(主席树)详解

    P3834 [模板]可持久化线段树 2(主席树) 题解 P3834 [[模板]可持久化线段树 2(主席树)] 1)静态求第k大数 可持久化线段树,不能用堆的方法存子结点了,所以用指针l表示左儿子r表示 ...

  3. 可持久化线段树——主席树

    前言: 最近心(po)血(yu)来(ya)潮(li)学习了一下主席树.(再不学就落伍了) 主席树,即可持久化线段树,支持维护和查询区间的第\(k\)大(小).区间不同种类个数等,基于线段树的思想之上 ...

  4. P3834-【模板】可持久化线段树 1(主席树)

    正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P3834 题意 给定一个长度为n的序列,有m个询问,求一个区间内的第k ...

  5. 主席树 - 可持久化线段树

    模板 P3834 [模板]可持久化线段树 2(主席树) 区间求第 \(k\) 大 模板代码 #include<bits/stdc++.h> using namespace std; #de ...

  6. 学习笔记:可持久化线段树(主席树):静态 + 动态

    学习笔记:可持久化线段树(主席树):静态 + 动态 前置知识: 线段树.线段树分享可以看:@秦淮岸.@ZYzzz.@妄想の岚がそこに 树状数组.\(BIT\)分享可以看:@T-Sherlock.Chi ...

  7. 【NOI2018】你的名字【后缀自动机】【可持久化线段树合并】【乱搞】

    题意:给一个串 SSS,qqq 次询问,每次给定串 TTT 和 l,rl,rl,r ,求有多少个本质不同的串是 TTT 的子串而不是 Sl-rS_{l\dots r}Sl-r​ 的子串. ∣S∣≤5× ...

  8. 【CF700E】Cool Slogans【后缀自动机】【可持久化线段树合并】【树上倍增】

    传送门 题意:给定字符串SSS,求一堆字符串s1,s2,s3,...,sks_1,s_2,s_3,...,s_ks1​,s2​,s3​,...,sk​,满足s1s_1s1​是SSS的子串,且sis_i ...

  9. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

  10. BZOJ.3218.a + b Problem(最小割ISAP 可持久化线段树优化建图)

    BZOJ UOJ 首先不考虑奇怪方格的限制,就是类似最大权闭合子图一样建图. 对于奇怪方格的影响,显然可以建一条边\((i\to x,p_i)\),然后由\(x\)向\(1\sim i-1\)中权值在 ...

最新文章

  1. FFT频谱泄露和加窗 (一)
  2. 如何在Visual Studio中“添加现有项”整个目录结构?
  3. FTP-工作原理及Vsftpd基础配置
  4. 5加载stm32 keil_快速入门STM32单片机-软件篇
  5. SecureCRT 中 python 命令行使用退格键(backspace)出现 ^H 解决办法
  6. while0表示什么意思_什么是意思表示,有哪些形式?
  7. 智能合约从入门到精通:Solidity Assembly
  8. 重操JS旧业第五弹:函数
  9. 20190708 帆软报表
  10. php输出最近N个月的起至时间戳
  11. python爬取景点数据看该去哪里玩——南京篇
  12. 【UnityEditor】制作一个unity ui 脚本自动生成器
  13. SPI FLASH 波形测量演示实例
  14. word打开html显示空白,电脑打开Word文档内容显示不全或显示空白怎么解决
  15. python代码调试工具_我猜你需要这个Python调试工具
  16. Android USB tethering相关代码
  17. Mac Xcode 更改编辑器文本字体大小
  18. 先序序列和中序序列构造二叉树,中序序列和后序序列构造二叉树
  19. 读书笔记: 博弈论导论 - 16 - 不完整信息的动态博弈 信号传递博弈
  20. 【经营智慧】002.赚钱主要靠知识和智慧

热门文章

  1. Opencv_HIGHGUI ERROR: V4L/V4L2: VIDIOC_S_CROP解决方案
  2. Swift 2.x 升为 swift 3后语法不兼容问题适配
  3. MySQL系列(三)
  4. 安卓手机清楚内置X5浏览器缓存
  5. python使用软件,输出,声明和if规则
  6. uva1382 Distant Galaxy
  7. 不会日语也能在日本点菜 | 通用篇
  8. body标签子级被默认client width截断的解决方法
  9. Redis设计与实现 - chapter7 压缩列表
  10. oracle两种用户认证方式