传送门

转换为判断,二分一个len,判断后缀起点在a -- b-mid+1 直接存不存在S,

使lcp(S,c)>= len,我们发现rank[S] 一定在c左右的一个范围内, 我们二分这个范围,用主席树判断就可以了

#include<bits/stdc++.h>
#define N 100050
using namespace std;int n,m,q;
char s[N];
int SA[N],rank[N],Height[N],y[N],c[N],tmp[N];
int st[N][20],Log[N];
struct Node{int ls,rs,val;
}t[N*30]; int rt[N],tot;void Sort(){for(int i=1;i<=m;i++) c[i] = 0;for(int i=1;i<=n;i++) c[rank[i]]++;for(int i=1;i<=m;i++) c[i] += c[i-1];for(int i=n;i>=1;i--) SA[c[rank[y[i]]]--] = y[i];
}void get_SA(){for(int i=1;i<=n;i++) rank[i] = s[i], y[i] = i;Sort();for(int k=1;k<=n;k<<=1){int ret = 0;for(int i=n-k+1;i<=n;i++) y[++ret] = i;for(int i=1;i<=n;i++) if(SA[i] > k) y[++ret] = SA[i] - k;Sort(); swap(rank,tmp); rank[SA[1]] = 1; int num = 1;for(int i=2;i<=n;i++){if(tmp[SA[i]] == tmp[SA[i-1]] && tmp[SA[i]+k] == tmp[SA[i-1]+k])rank[SA[i]] = num;else rank[SA[i]] = ++num;} m = num;}
}
void get_Height(){int k = 0;for(int i=1;i<=n;i++){if(rank[i]==1) continue;int j = SA[rank[i]-1]; if(k) k--;while(i+k<=n && j+k<=n && s[i+k]==s[j+k]) k++;Height[rank[i]] = k;}
} void get_ST(){for(int i=2;i<=n;i++) Log[i] = Log[i/2] + 1;for(int i=1;i<=n;i++) st[i][0] = Height[i];for(int i=1;(1<<i)<=n;i++)for(int j=1;j+(1<<i)-1<=n;j++)st[j][i] = min(st[j][i-1], st[j+(1<<(i-1))][i-1]);
}
int Lcp(int l,int r){l++; int x = Log[r-l+1];return min(st[l][x], st[r-(1<<x)+1][x]);
}
void Build(int &x,int l,int r){x = ++tot;if(l==r) return;int mid = (l+r) >> 1;Build(t[x].ls, l, mid);Build(t[x].rs, mid+1, r);
}
void Insert(int &x,int last,int l,int r,int pos){x = ++tot; t[x] = t[last]; t[x].val++;if(l==r) return;int mid = (l+r) >> 1;if(pos<=mid) Insert(t[x].ls, t[last].ls, l, mid, pos);else Insert(t[x].rs, t[last].rs, mid+1, r, pos);
}
int check(int a,int b,int l,int r,int L,int R){if(L<=l && r<=R) return t[b].val - t[a].val;int mid = (l+r) >> 1, ans = 0;if(L<=mid) ans += check(t[a].ls, t[b].ls, l, mid, L, R);if(R>mid) ans += check(t[a].rs, t[b].rs, mid+1, r, L, R);return ans;
}void get_LR(int st,int len,int &L,int &R){int l=1,r=rank[st];while(l<r){int mid = (l+r) >> 1;if(Lcp(mid,rank[st])>=len) r = mid;else l = mid+1;} L = l;l = rank[st], r = n;while(l<r){int mid = (l+r+1) >> 1;if(Lcp(rank[st],mid)>=len) l = mid;else r = mid-1;} R = l;
}
int calc(int a,int b,int c,int d){int l = 0, r = min(b-a, d-c) + 1;while(l<r){int mid = (l+r+1) >> 1;int L = 0, R = 0; get_LR(c,mid,L,R);if(check(rt[a-1],rt[b-mid+1],1,n,L,R)) l = mid;else r = mid-1;} return l;
}
int main(){scanf("%d%d%s",&n,&q,s+1);m = 127; get_SA(); get_Height(); get_ST();Build(rt[0],1,n); for(int i=1;i<=n;i++) Insert(rt[i], rt[i-1], 1, n, rank[i]);while(q--){int a,b,c,d;scanf("%d%d%d%d",&a,&b,&c,&d);printf("%d\n",calc(a,b,c,d));} return 0;
}

P4094 [HEOI2016/TJOI2016]字符串 [SA + 主席树]相关推荐

  1. 洛谷P4094 [HEOI2016/TJOI2016]字符串【后缀数组+主席树+st表】

    时空限制 2000ms / 256MB 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确 ...

  2. 主席树 + 后缀数组求LCP + 二分套二分 ---- P4094 [HEOI2016/TJOI2016]字符串

    题目链接 题目大意: 解题思路: 设我们的答案为midmidmid(注意这里有坑是[a,b][a,b][a,b]的所有子串和[c,d][c,d][c,d]这个子串的最长lcplcplcp),那么我们会 ...

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

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

  4. [HEOI2016/TJOI2016]字符串 (后缀数组+主席树+二分)

    description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为 n 的字符串 s,和 m 个问题.佳媛姐姐必须正确回答这 m 个问 ...

  5. HEOI2016/TJOI2016 字符串问题

    题目链接:戳我 非常不好意思,因为想要排版,所以今天先只把代码贴出来,明天补题解. 40pts暴力:直接暴力匹配 #include<iostream>#include<cstring ...

  6. [BZOJ4556][TJOI2016HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1360  Solved: 545 ...

  7. 洛谷P4094 - [TJOI2016]字符串

    Portal Description 给出一个字符串\(s(|s|\leq10^5)\)和\(m\)次询问,每次询问子串\(s[x_1..x_2]\)的所有子串和\(s[y_1..y_2]\)的最长公 ...

  8. BZOJ3473:字符串(后缀数组,主席树,二分,ST表)

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

  9. [2020.11.26NOIP模拟赛]勇者的后缀【SA,RMQ,主席树,二分】

    正题 题目链接:https://www.luogu.com.cn/problem/U142356?contestId=37784 题目大意 一个字符串,询问给出(x,l,r)(x,l,r)(x,l,r ...

最新文章

  1. python3实现mysql导出excel
  2. 《深入理解C++11:C++ 11新特性解析与应用》——3.2 委派构造函数
  3. Caffe学习笔记2
  4. wxWidgets:wxHtmlCellEvent类用法
  5. 《大数据日知录:架构与算法》前言
  6. Linux下c/c++项目代码覆盖率的产生方法
  7. java printf与println_浅析Java中print、printf、println的区别
  8. ionic2+angular2中踩的那些坑
  9. 2021,我的年终总结......
  10. 2011 5月13日
  11. 进来偷学一招,数据归档二三事儿
  12. php soap 用法,php soap用法
  13. LTE无线接入网的架构
  14. HSPICE物理模型仿真——添加variation时利用seed产生伪随机分布
  15. php开发微信小程序教程,从零开始开发微信小程序步骤(三)
  16. 《Google软件测试之道》三、好的经验沉淀
  17. Weighted Quick Union
  18. vim实用指南(9)vimdiff好用的可视化文本对比工具
  19. Java笔记——Java多线程~
  20. php注册登录详解_实例讲解php用户注册与登录页面

热门文章

  1. CMDN Club #19: Windows 8 Dev BootCamp - Win8开发知识与产品实践
  2. AdGuard更多规则推荐
  3. js过滤对象中值为空的属性
  4. 约翰·卡马克和他的id Software
  5. 鲲鹏聚数,华为宣布联合高校发起GaussDB金种子发展计划
  6. 如何将台式机的网络共享给另外一台台式机
  7. 【Practical】CSDN图片去除水印
  8. 为什么我们要学操作系统?
  9. 倒三角打印乘法口诀python_Python打印乘法口诀表
  10. matlab 期权图,欧式看涨期权定价作图|MATLAB 程序化交易(量化投资)|MATLAB技术论坛 - Powered by Discuz!...