题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4556

本来只要查 ht[ ] 数组上的前驱和后继就行,但有长度的限制。可以二分答案解决!然后用主席树查区间内的 ht[ ] 的前驱和后继即可。(主席树弄对 rk 的权值线段树)

在主席树上走的复杂度应该不会比二分然后查看主席树的 log2 更差吧。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return a<b?a:b;}
const int N=1e5+,K=,M=N*K;
int n,sa[N],rk[N],tp[N],tx[N],ht[N][K],lg[N],bin[K];
int tot,ls[M],rs[M],sm[M],rt[N];
char s[N];
void Rsort(int n,int nm)
{
for(int i=;i<=nm;i++)tx[i]=;
for(int i=;i<=n;i++)tx[rk[i]]++;
for(int i=;i<=nm;i++)tx[i]+=tx[i-];
for(int i=n;i;i--)sa[tx[rk[tp[i]]]--]=tp[i];
}
void get_sa(int n)
{
int nm=;
for(int i=;i<=n;i++)tp[i]=i,rk[i]=s[i]-'a'+;
Rsort(n,nm);
for(int k=;;k<<=)
{
int tot=;
for(int i=n-k+;i<=n;i++)tp[++tot]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++tot]=sa[i]-k;
Rsort(n,nm);memcpy(tp,rk,sizeof rk);
nm=;rk[sa[]]=;
for(int i=;i<=n;i++)//i=2!!!!not i=1
{
int u=sa[i]+k,v=sa[i-]+k;// if(u>n)u=0; if(v>n)v=0;
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[u]==tp[v])?nm:++nm;
}
if(nm==n)break;
}
}
void get_ht(int n)
{
for(int i=,k=,j;i<=n;i++)
{
if(rk[i]==)continue;//
for((k?k--:),j=sa[rk[i]-];i+k<=n&&j+k<=n&&s[i+k]==s[j+k];k++);
//////i+k<=n&&j+k<=n
ht[rk[i]][0]=k;
}
for(int i=;i<=n;i++)lg[i]=lg[i>>]+;
bin[]=;for(int i=;i<=lg[n];i++)bin[i]=bin[i-]<<;
//i<=lg[n] not bin[i-1]<lg[n]!!!(should bin[i-1]<n)
for(int t=;t<=lg[n];t++)
for(int i=;i+bin[t]-<=n;i++)
ht[i][t]=Mn(ht[i][t-],ht[i+bin[t-]][t-]);
}
void ins(int &cr,int pr,int l,int r,int p)
{
cr=++tot;ls[cr]=ls[pr];rs[cr]=rs[pr];sm[cr]=sm[pr]+;
if(l==r)return; int mid=l+r>>;
if(p<=mid)ins(ls[cr],ls[pr],l,mid,p);
else ins(rs[cr],rs[pr],mid+,r,p);
}
int qry(int r1,int r2,int l,int r,int p)
{
if(sm[r2]-sm[r1]==)return ;
if(l==r)return l; int mid=l+r>>,d=;//d=0!!
if(p>mid)d=qry(rs[r1],rs[r2],mid+,r,p);
if(d)return d;
return qry(ls[r1],ls[r2],l,mid,p);
}
int qry2(int r1,int r2,int l,int r,int p)
{
if(sm[r2]-sm[r1]==)return ;
if(l==r)return l; int mid=l+r>>,d=;
if(p<=mid)d=qry2(ls[r1],ls[r2],l,mid,p);//qry2 not qry
if(d)return d;
return qry2(rs[r1],rs[r2],mid+,r,p);
}
int qry_ht(int l,int r)
{
if(l==r)return n-sa[l]+;//////n-sa[l]+1 not n-l+1!!!
int d=lg[r-l];
return Mn(ht[l+][d],ht[r-bin[d]+][d]);//l+1!!!not l
}
int main()
{
int Q;n=rdn();Q=rdn();scanf("%s",s+);//+1
get_sa(n);get_ht(n);
for(int i=;i<=n;i++)ins(rt[i],rt[i-],,n,rk[i]);
int l1,r1,l2,r2;
while(Q--)
{
l1=rdn();r1=rdn();l2=rdn();r2=rdn();
int l=,r=Mn(r1-l1+,r2-l2+),ans=;
while(l<=r)
{
int mid=l+r>>,d=r1-mid+;
int p1=qry(rt[l1-],rt[d],,n,rk[l2]);
int p2=qry2(rt[l1-],rt[d],,n,rk[l2]);
int tmp=Mx((p1?qry_ht(p1,rk[l2]):),(p2?qry_ht(rk[l2],p2):));
if(tmp>=mid)ans=mid,l=mid+;
else r=mid-;
}
printf("%d\n",ans);
}
return ;
}

最新文章

  1. libev安装与示例程序编译运行
  2. HDU5492 Find a path[DP 方差]
  3. 表单 - Form - EasyUI提供的表单异步提交
  4. perl检查变量是否定义
  5. Lua __index元方法
  6. 如何使用mybatis《三》
  7. 通过两个GPS计算两个GPS点的距离
  8. SDOI 2010 and SXOI 2014 地精部落 (递推)
  9. ZOJ 1122 Clock(模拟)
  10. PureMVC(JS版)源码解析(一):观察者模式解析
  11. cf437D The Child and Zoo
  12. 【DSA MOOC】有序向量二分查找的三个 版本
  13. Android使用开源项目Xutils实现多线程下载文件
  14. TIdTCPClient 详解
  15. scrapy使用
  16. 防止SpringMVC拦截器拦截js等静态资源文件
  17. 小米Play获取ROOT权限的经验
  18. Linux 平台下 RMAN 全备 和 增量备份 shell 脚本
  19. 【python练习题】程序7
  20. AT2165 Median Pyramid Hard 二分答案 脑洞题

热门文章

  1. iOS UI-三种简单的动画设置
  2. 感知器、logistic与svm 区别与联系
  3. cas AuthenticationFilter
  4. .net面试题精选
  5. 练习vue(class,style属性)
  6. 51nod1482
  7. superset 安装配置
  8. web项目中的路径问题
  9. L1-003 个位数统计
  10. MyEclipse WebSphere开发教程:WebSphere 8安装指南(一)