您的位置:首页 > 其它

BZOJ4556 [Tjoi2016&Heoi2016]字符串

2016-06-14 10:10 405 查看
恩,我们进行一些瞎YY,首先询问s[a~b]的所有子串与S[c~d]的最长LCP其实相当于询问s[a~b]的所有后缀与s[c~d]的最长LCP与这个子串的长度还有c~d的长度取min

进一步转化设suf[i]表示S的从第i个字符开始的后缀,则其实相当于询问这个



可以把d-c+1提到外面,就变成



这样只需要考虑左面的,考虑若答案为l(l<=d-c+1),则作为答案的后缀不可能取在i>b-l+1的位置,而在a<=i<=b-l+1的范围内,只要LCP(suf[i],suf[c])>=l,那么s[i~b]就是一个与s[c~d]有长度为l的LCP的子串

这样我们可以在<=d-c+1的范围内二分答案,每次只要判断a<=i<=b-mid+1的范围内是否存在LCP(suf[i],suf[c])>=mid即可,这个判断可以先建一颗后缀树,在后缀树上倍增找到suf[c]的最浅的长度>=mid的祖先,然后判断这个祖先的子树内是否有a<=i<=b-mid+1的后缀即可,这个可以用主席树

复杂度 O(m log^2 n)

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 200010
#define MAXM 4000010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
struct vec{
int to;
int fro;
};
int fa[MAXN],son[MAXN][26],mx[MAXN];
int rt,lst,tot;
int n,m;
char s[MAXN];
int Son[MAXM][2],Siz[MAXM];
int Tot;
int Rt[MAXN];
vec mp[MAXN];
int tai[MAXN],cnt;
int dfn[MAXN],ndf[MAXN],siz[MAXN],tim;
int Fa[MAXN][20];
int dep[MAXN];
int P[MAXN];
vector<int>tp[MAXN];
inline void be(int x,int y){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
}
void ins(int x){
int np=++tot,p=lst;
mx[np]=mx[p]+1;
while(p&&!son[p][x]){
son[p][x]=np;
p=fa[p];
}
if(!p){
fa[np]=rt;
}else{
int q=son[p][x];
if(mx[q]==mx[p]+1){
fa[np]=q;
}else{
int nq=++tot;
mx[nq]=mx[p]+1;
memcpy(son[nq],son[q],sizeof(son[q]));
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
while(p&&son[p][x]==q){
son[p][x]=nq;
p=fa[p];
}
}
}
lst=np;
}
void dfs(int x){
int i,j,t,y;
dfn[x]=++tim;
ndf[tim]=x;
siz[x]=1;
dep[x]=dep[Fa[x][1]]+1;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
for(t=x,j=1;t;j++){
Fa[y][j]=t;
t=Fa[t][j];
}
dfs(y);
siz[x]+=siz[y];
}
}
void change(int &x,int xx,int l,int r,int p){
x=++Tot;
memcpy(Son[x],Son[xx],sizeof(Son[x]));
Siz[x]=Siz[xx]+1;
if(l==r){
return ;
}
int mid=l+r>>1;
if(p<=mid){
change(Son[x][0],Son[xx][0],l,mid,p);
}else{
change(Son[x][1],Son[xx][1],mid+1,r,p);
}
}
int anc(int x,int y){
int i;
for(i=19;i;i--){
if(mx[Fa[x][i]]>=y){
x=Fa[x][i];
}
}
return x;
}
int ask(int x,int xx,int y,int z,int l,int r){
if(y==l&&z==r){
return Siz[xx]-Siz[x];
}
int mid=y+z>>1;
if(r<=mid){
return ask(Son[x][0],Son[xx][0],y,mid,l,r);
}else if(l>mid){
return ask(Son[x][1],Son[xx][1],mid+1,z,l,r);
}else{
return ask(Son[x][0],Son[xx][0],y,mid,l,mid)+ask(Son[x][1],Son[xx][1],mid+1,z,mid+1,r);
}
}
bool OK(int x,int y,int z){
return ask(Rt[dfn[x]-1],Rt[dfn[x]+siz[x]-1],1,n,y,z);
}
int main(){
lst=rt=tot=1;
int i,j,x,y,xx,yy;
scanf("%d%d",&n,&m);
scanf("%s",s+1);
int p=rt;
for(i=n;i;i--){
ins(s[i]-'a');
p=son[p][s[i]-'a'];
P[i]=p;
tp[P[i]].push_back(i);
}
for(i=2;i<=tot;i++){
be(fa[i],i);
}
dfs(1);
for(i=1;i<=tim;i++){
Rt[i]=Rt[i-1];
for(j=0;j<tp[ndf[i]].size();j++){
change(Rt[i],Rt[i],1,n,tp[ndf[i]][j]);
}
}
while(m--){
scanf("%d%d%d%d",&x,&y,&xx,&yy);
int l=1,r=min(yy-xx+1,y-x+1);
int ans=0;
while(l<=r){
int mid=l+r>>1;
if(OK(anc(P[xx],mid),x,y-mid+1)){
ans=mid;
l=mid+1;
}else{
r=mid-1;
}
}
printf("%d\n",ans);
}
return 0;
}

/*
8 1
ababcabc
1 3 6 8
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: