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; }