CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心
Posted guangheli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心相关的知识,希望对你有一定的参考价值。
后缀自动机 + 线段树合并的裸题.
我这种大菜逼都秒切的题目,一定是送分题.
#include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #define maxn 220000 using namespace std; int n; int rt[maxn]; namespace tr #define mid ((l+r)>>1) #define lson t[x].l #define rson t[x].r int cnt; int newnode() return ++cnt; struct Node int l,r,sumv; t[maxn * 50]; int merge(int u,int v) if(!u||!v) return u+v; int x=newnode(); t[x].sumv=t[u].sumv+t[v].sumv; lson=merge(t[u].l,t[v].l); rson=merge(t[u].r,t[v].r); return x; void update(int &x,int l,int r,int k,int delta) if(!x)x=newnode(); t[x].sumv+=delta; if(l==r) return; if(k<=mid) update(lson, l, mid, k, delta); else update(rson, mid + 1, r, k, delta); int query(int x,int l,int r,int L,int R) if(!x || L>R)return 0; if(l>=L&&r<=R) return t[x].sumv; int tmp=0; if(L<=mid) tmp+=query(lson,l,mid,L,R); if(R>mid) tmp+=query(rson, mid+1,r,L,R); return tmp; #undef lson #undef rson ; namespace SAM int tot,last; int len[maxn], ch[maxn][30], f[maxn], rk[maxn], C[maxn]; void init() tot = last = 1; void extend(int c) int np=++tot,p=last; last=np, len[np]=len[p]+1; while(p&&!ch[p][c]) ch[p][c]=np,p=f[p]; if(!p) f[np]=1; else int q=ch[p][c]; if(len[q]==len[p]+1) f[np]=q; else int nq=++tot; len[nq]=len[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); f[nq]=f[q],f[np]=f[q]=nq; while(p&&ch[p][c]==q) ch[p][c]=nq, p=f[p]; tr::update(rt[np], 1, n, len[np], 1); void prepare() int i,j; for(i=1;i<=tot;++i) ++C[len[i]]; for(i=1;i<=tot;++i) C[i]+=C[i-1]; for(i=1;i<=tot;++i) rk[C[len[i]]--]=i; for(i=tot;i>=1;--i) j=rk[i]; rt[f[j]]=tr::merge(rt[f[j]], rt[j]); ; char str[maxn], T[maxn], stac[maxn]; int cur[maxn]; int main() int i,j,Q; // setIO("input"); scanf("%s",str+1); n=strlen(str+1); SAM::init(); for(i=1;i<=n;++i) SAM::extend(str[i]-‘a‘); SAM::prepare(); scanf("%d",&Q); while(Q--) int l,r,_len,trace=0,top=0,L; scanf("%d%d%s",&l,&r,T+1); L=l; _len=strlen(T+1); cur[0]=1; for(i=1;i<=min(_len,n-1);++i) int c=T[i]-‘a‘; if(SAM::ch[cur[i-1]][c] && tr::query(rt[SAM::ch[cur[i-1]][c]], 1, n, l, r)) cur[i]=SAM::ch[cur[i-1]][c]; ++l, trace=i, stac[++top]=T[i]; else break; T[0]=‘a‘; int flag=0; for(i=min(n-1,trace);i>=0;--i) int c= i + 1 > _len ? -1 : T[i+1] - ‘a‘; // if(flag) break; for(j=c+1;j<27;++j) if(SAM::ch[cur[i]][j] && tr::query(rt[SAM::ch[cur[i]][j]] , 1, n, l, r)) flag=1; stac[++top]=‘a‘+j; break; if(flag) break; --l; --top; if(!flag) printf("-1\n"); else for(i=1;i<=top;++i) printf("%c",stac[i]); printf("\n"); return 0;
以上是关于CF1037H Security 后缀自动机 + right集合线段树合并 + 贪心的主要内容,如果未能解决你的问题,请参考以下文章