luoguP6640 [BJOI2020] 封印 SAM+线段树
不难的一道字符串题.
建立 $T$ 的 SAM,然后根据 $S$ 中的询问按照右端点离线,依次在 $T$ 的 SAM 上匹配.
查询的时候分两种情况讨论一下,用线段树维护就行了.
code:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 400009
#define ll long long
#define lson now<<1
#define rson now<<1|1
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
char S[N],T[N];
int last,tot,n,m,sta,len;
int mx[N],ch[N][2],pre[N],ans[N];
struct data {
int x,y;
data() { x=y=0; }
data operator+(const data b) const {
data c;
c.x=max(x,b.x);
c.y=max(y,b.y);
return c;
}
}s[N<<2];
struct que {
int x,y,id;
bool operator<(const que b) const {
return y<b.y;
}
}a[N];
void update(int l,int r,int now,int p,int v,int ty) {
if(l==r) {
if(ty==0) s[now].x=max(s[now].x,v);
if(ty==1) s[now].y=max(s[now].y,v);
return;
}
int mid=(l+r)>>1;
if(p<=mid) update(l,mid,lson,p,v,ty);
else update(mid+1,r,rson,p,v,ty);
s[now]=s[lson]+s[rson];
}
data query(int l,int r,int now,int L,int R) {
if(l>=L&&r<=R) return s[now];
int mid=(l+r)>>1;
if(L<=mid&&R>mid) return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
else if(L<=mid) return query(l,mid,lson,L,R);
else return query(mid+1,r,rson,L,R);
}
void extend(int c) {
int np=++tot,p=last;
mx[np]=mx[p]+1,last=np;
for(;p&&!ch[p][c];p=pre[p]) ch[p][c]=np;
if(!p) pre[np]=1;
else {
int q=ch[p][c];
if(mx[q]==mx[p]+1) pre[np]=q;
else {
int nq=++tot;
mx[nq]=mx[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
pre[nq]=pre[q],pre[q]=pre[np]=nq;
for(;p&&ch[p][c]==q;p=pre[p]) ch[p][c]=nq;
}
}
}
// 当前位置为 pos
void upd(int pos) {
int c=S[pos]-'a';
if(!sta) sta=1;
for(;sta&&!ch[sta][c];sta=pre[sta],len=mx[sta]);
if(ch[sta][c]) sta=ch[sta][c],++len;
// 当前匹配长度
if(len) {
update(1,n,1,pos-len+1,len,0);
update(1,n,1,pos-len+1,pos,1);
}
}
int main() {
// setIO("input");
int Q;
scanf("%s%s",S+1,T+1);
n=strlen(S+1),m=strlen(T+1),last=tot=1;
for(int i=1;i<=m;++i) extend(T[i]-'a');
scanf("%d",&Q);
for(int i=1;i<=Q;++i) {
scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i;
}
sort(a+1,a+1+Q);
for(int i=1,j=1;i<=Q;++i) {
for(;j<=a[i].y;++j) upd(j);
data a1=query(1,n,1,1,a[i].x);
data a2=query(1,n,1,a[i].x,a[i].y);
ans[a[i].id]=max(0,max(a1.y-a[i].x+1,a2.x));
}
for(int i=1;i<=Q;++i) printf("%d\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号