解析

很好的一道SA的题。(觉得完全可以评黑了啊qwq)
我一开始拿SAM和线段树硬做,不断修正最后发现自己无法在可接受复杂度内解决的问题,直接GG…
垃圾数据还骗到了50分
所以写一道题之前还是要先想仔细了,确定整个流程没有锅再写吧,尽量避免写一半发现不对再修正甚至直接假掉的情况,还能使实现时更加系统简洁。

考虑SA。
为什么搜SAM的tag结果全是拿SA做的啊。

答案显然具有单调性,考虑check二分的答案 LLL 是否合法。
合法的情况可以等价抽象为:区间内存在两个后缀 p,qp,qp,q,使得 lcp(p,q)≤Llcp(p,q)\le Llcp(p,q)≤L 。
用类似品酒大会的思路(这个思路似乎非常常见好用),把所有 hi≥Lh_i\ge Lhi​≥L 的 i,i−1i,i-1i,i−1 合并,最后就是看区间内是否有两个点在同一个集合内。

在线段树上存储每个结点左侧在同一集合内的结点最靠右的位置,问题转化为查询 [l,r−L+1][l,r-L+1][l,r−L+1] 的最大值是否大于 LLL。
这个线段树可以用主席树维护,每个并查集集合维护一个 set,启发式合并暴力查找前驱后缀即可。

时空复杂度 O(nlog2n)O(nlog^2n)O(nlog2n)。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
const int N=1e5+100;
const int M=1e6+100;
const int mod=1e9;int n,m;
char s[N];int sa[N],rk[N],id[N],oldrk[N],cnt[N];
int h[N];
void SA(){int m=300;//printf("%s\n",s+1);for(int i=1;i<=n;i++) ++cnt[rk[i]=s[i]];for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;for(int w=1;m!=n;w<<=1){int p=0;for(int i=n;i>n-w;i--) id[++p]=i;for(int i=1;i<=n;i++){if(sa[i]>w) id[++p]=sa[i]-w;}memset(cnt,0,sizeof(cnt));memcpy(oldrk,rk,sizeof(rk));for(int i=1;i<=n;i++) ++cnt[rk[id[i]]];for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];for(int i=n;i>=1;i--) sa[cnt[rk[id[i]]]--]=id[i];m=0;for(int i=1;i<=n;i++){if(oldrk[sa[i]]==oldrk[sa[i-1]]&&oldrk[sa[i]+w]==oldrk[sa[i-1]+w]) rk[sa[i]]=m;else rk[sa[i]]=++m;}}for(int i=1,y=0;i<=n;i++){if(y) --y;while(s[i+y]==s[sa[rk[i]-1]+y]) ++y;h[rk[i]]=y;}//for(int i=1;i<=n;i++) printf("i=%d %s sa=%d h=%d\n",i,s+sa[i],sa[i],h[i]);return;
}struct tree{int ls,rs,mx;
};
const int C=100;
struct Sefment_Tree{tree tr[N*C];int tot;#define mid ((l+r)>>1)inline int copy(int x){tr[++tot]=tr[x];assert(tot<N*C);return tot;}inline void pushup(int k){tr[k].mx=max(tr[tr[k].ls].mx,tr[tr[k].rs].mx);return;}int ask(int k,int l,int r,int x,int y){if(!k) return 0;if(x<=l&&r<=y) return tr[k].mx;int res=0;if(x<=mid) res=max(res,ask(tr[k].ls,l,mid,x,y));if(y>mid) res=max(res,ask(tr[k].rs,mid+1,r,x,y));return res;}void change(int &k,int l,int r,int p,int w){k=copy(k);if(l==r){tr[k].mx=max(tr[k].mx,w);return;}if(p<=mid) change(tr[k].ls,l,mid,p,w);else change(tr[k].rs,mid+1,r,p,w);pushup(k);}#undef mid
}t;
int rt[N];set<int>S[N];
set<int>::iterator it;
inline int Suf(int k,int w){it=S[k].lower_bound(w);return (it==S[k].end())?0:(*it);
}
inline int Pre(int k,int w){it=S[k].lower_bound(w);if(it==S[k].begin()) return 0;else{it--;return (*it);}
}
int fa[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y,int L){//printf("merge: %d %d L=%d\n",x,y,L); x=find(x);y=find(y);if(S[x].size()>S[y].size()) swap(x,y);//printf("  x=%d y=%d\n",x,y);for(int now:S[x]){int pre=Pre(y,now),suf=Suf(y,now);if(pre) t.change(rt[L],1,n,now,pre);if(suf) t.change(rt[L],1,n,suf,now);//printf("  ins:now=%d pre=%d suf=%d\n",now,pre,suf);}for(int now:S[x]){S[y].insert(now);}S[x].clear();fa[x]=y;return;
}struct node{int h,id;bool operator < (const node o)const{return h>o.h;}
}p[N];signed main(){#ifndef ONLINE_JUDGE//freopen("a.in","w",stdin);//freopen("a.out","w",stdin);#endifn=read();m=read();//printf("%d\n",n);scanf(" %s",s+1);SA();int num(0);for(int i=1;i<=n;i++){fa[i]=i;S[i].insert(i);if(i>1) p[++num]=(node){h[i],i};}sort(p+1,p+1+num);int pl=1;for(int i=n;i>=0;i--){rt[i]=rt[i+1];while(pl<=num&&p[pl].h==i){if(p[pl].id>1){int x=sa[p[pl].id],y=sa[p[pl].id-1];merge(x,y,i);}++pl;}}for(int i=1;i<=m;i++){int l=read(),r=read(),st=0,ed=n;while(st<ed){int mid=(st+ed+1)>>1;if(t.ask(rt[mid],1,n,l,r-mid+1)>=l) st=mid;else ed=mid-1;}printf("%d\n",st);}return 0;
}
/*
8 1
aabaabba
4 5*/

洛谷P7361:拜神(SA、二分、主席树、启发式合并)相关推荐

  1. 【BZOJ-3123】森林 主席树 + 启发式合并

    3123: [Sdoi2013]森林 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 2738  Solved: 806 [Submit][Statu ...

  2. YBTOJ洛谷P2839:最大中位数(主席树、二分答案)

    遇事不决,二分试试 解析 很好的一道题 真是把主席树玩明白了 一个关于中位数的常用trick: 二分答案mid,把>=mid的看成1,<mid的看成-1,然后看最大子段和是否>=0 ...

  3. 【JZOJ3794】【洛谷P1383】高级打字机【主席树】

    题目大意: 题目链接: 洛谷:https://www.luogu.org/problemnew/show/P1383 JZOJ:https://jzoj.net/senior/#main/show/3 ...

  4. 洛谷P2839 [国家集训队]middle(主席树)

    P2839 [国家集训队]middle 我们可以考虑二分中位数 checkcheckcheck 答案,那么我们对于某个值 midmidmid ,把 [l,r][l,r][l,r] 内的所有小于 mid ...

  5. 洛谷 P3302 [SDOI2013]森林 主席树+启发式合并

    click here~:https://www.luogu.org/problem/P3302 emmm这个题是真的烦 一看题发现这题不是count on a tree的升级版么 如果一点思路没有的话 ...

  6. [SDOI2013]森林(树上主席树+启发式合并+lca)

    链接:https://ac.nowcoder.com/acm/problem/20577 来源:牛客网 题目描述 小Z有一片森林,含有N个节点,每个节点上都有一个非负整数作为权值.初始的时候,森林中有 ...

  7. 洛谷P4559 [JSOI2018]列队 【70分二分 + 主席树】

    题目链接 洛谷P4559 题解 只会做\(70\)分的\(O(nlog^2n)\) 如果本来就在区间内的人是不用动的,区间右边的人往区间最右的那些空位跑,区间左边的人往区间最左的那些空位跑 找到这些空 ...

  8. 洛谷P1462 通往奥格瑞玛的道路 二分答案+最短路SPFA

    洛谷P1462 通往奥格瑞玛的道路 二分答案+最短路SPFA 二分交费最多的一次的钱数 然后只将符合要求的边加入图中 如果到终点的最短路大于等于血量 或者直接起点不能到达终点 那么说明不符合要求 需要 ...

  9. 洛谷 P4094 [HEOI2016/TJOI2016]字符串 后缀数组+二分+主席树

    题目链接 后缀数组 题目分析: sa[i] – 第i小的后缀的编号 rank[i] --编号为i的后缀排第几: height[i] – 第i和第i-1的最长lcp最长公共前缀: 1.二分答案,答案肯定 ...

最新文章

  1. zynq tcp如何从网口发数据_ZYNQ_PL与PS的DDR交互
  2. c语言连接mysql_聊聊数据库MySQL、SqlServer、Oracle的区别,哪个更适合你?
  3. java泛型方法无参_从头再来:Java泛型(开发必须知道的)
  4. 中国体力活动监测器(PAM)市场趋势报告、技术动态创新及市场预测
  5. 什么是Asp.net Core?和 .net core有什么区别?(转)
  6. 视频编解码之H.264
  7. Loadrunner脚本录制执行
  8. ORACLE数据库日志路径在哪里,查询方式
  9. 通过端口查看进程和通过进程查看端口
  10. 肿瘤浸润淋巴细胞的扩增方法学评估
  11. iphone/ipad 连接smb服务器,备份照片
  12. SQL学习笔记——数据更新update语句的使用
  13. 求生之路服务器列表只显示ip,L4DL4D2 玩家进入退出+玩家转队伍SteamIdIP+国家+城市显示SQL版本 SP源码 2.4(2013-10-15更新)...
  14. 分享16个经典面试问题回答思路
  15. aliyun的产品都是有哪些,主要是做什么的呢?
  16. 基于java的奖学金评定系统设计与实现
  17. 云管平台监控实践分享
  18. java html转为word_Java如何将html转换成word
  19. java-net-php-python-jsp学生党团管理信息系统2020演示录像计算机毕业设计程序
  20. 行车记录仪效果由=方案(主控芯片)+镜头+图像传感器

热门文章

  1. 弹性式分布数据集RDD——Pyspark基础 (二)
  2. unity 坐标系转换_Unity的几种坐标系及相互转换
  3. mysql序列increment_MySQL 序列 AUTO_INCREMENT
  4. linux 创建ll,两台linux建立GRE隧道
  5. python二维列表写入excel_用Python实现合并excel列表
  6. tankwar java_TankWar 单机(JAVA版) 版本0.3 画出坦克
  7. php网站开发期末大作业,大学生期末网页大作业
  8. 如何在mysql中打开mongodb_图解:如何从MySQL移植到MongoDB
  9. 开启事物_《原神》全新角色甘雨登场 「浮生孰来」活动祈愿开启_新闻资讯_最新手游时评_原创手游资讯...
  10. action评测 osmo_前后双屏 大疆OSMO ACTION运动相机评测