日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

洛谷P7361:拜神(SA、二分、主席树、启发式合并)

發布時間:2023/12/3 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 洛谷P7361:拜神(SA、二分、主席树、启发式合并) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

解析

很好的一道SA的題。(覺得完全可以評黑了啊qwq)
我一開始拿SAM和線段樹硬做,不斷修正最后發現自己無法在可接受復雜度內解決的問題,直接GG…
垃圾數據還騙到了50分
所以寫一道題之前還是要先想仔細了,確定整個流程沒有鍋再寫吧,盡量避免寫一半發現不對再修正甚至直接假掉的情況,還能使實現時更加系統簡潔。

考慮SA。
為什么搜SAM的tag結果全是拿SA做的啊。

答案顯然具有單調性,考慮check二分的答案 LLL 是否合法。
合法的情況可以等價抽象為:區間內存在兩個后綴 p,qp,qp,q,使得 lcp(p,q)≤Llcp(p,q)\le Llcp(p,q)L
用類似品酒大會的思路(這個思路似乎非常常見好用),把所有 hi≥Lh_i\ge Lhi?Li,i?1i,i-1i,i?1 合并,最后就是看區間內是否有兩個點在同一個集合內。

在線段樹上存儲每個結點左側在同一集合內的結點最靠右的位置,問題轉化為查詢 [l,r?L+1][l,r-L+1][l,r?L+1] 的最大值是否大于 LLL
這個線段樹可以用主席樹維護,每個并查集集合維護一個 set,啟發式合并暴力查找前驅后綴即可。

時空復雜度 O(nlog2n)O(nlog^2n)O(nlog2n)

#include<bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define debug(...) fprintf(stderr,__VA_ARGS__) #define ok debug("OK\n") inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; } const int N=1e5+100; const int M=1e6+100; const int mod=1e9;int n,m; char s[N];int sa[N],rk[N],id[N],oldrk[N],cnt[N]; int h[N]; void SA(){int m=300;//printf("%s\n",s+1);for(int i=1;i<=n;i++) ++cnt[rk[i]=s[i]];for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;for(int w=1;m!=n;w<<=1){int p=0;for(int i=n;i>n-w;i--) id[++p]=i;for(int i=1;i<=n;i++){if(sa[i]>w) id[++p]=sa[i]-w;}memset(cnt,0,sizeof(cnt));memcpy(oldrk,rk,sizeof(rk));for(int i=1;i<=n;i++) ++cnt[rk[id[i]]];for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];for(int i=n;i>=1;i--) sa[cnt[rk[id[i]]]--]=id[i];m=0;for(int i=1;i<=n;i++){if(oldrk[sa[i]]==oldrk[sa[i-1]]&&oldrk[sa[i]+w]==oldrk[sa[i-1]+w]) rk[sa[i]]=m;else rk[sa[i]]=++m;}}for(int i=1,y=0;i<=n;i++){if(y) --y;while(s[i+y]==s[sa[rk[i]-1]+y]) ++y;h[rk[i]]=y;}//for(int i=1;i<=n;i++) printf("i=%d %s sa=%d h=%d\n",i,s+sa[i],sa[i],h[i]);return; }struct tree{int ls,rs,mx; }; const int C=100; struct Sefment_Tree{tree tr[N*C];int tot;#define mid ((l+r)>>1)inline int copy(int x){tr[++tot]=tr[x];assert(tot<N*C);return tot;}inline void pushup(int k){tr[k].mx=max(tr[tr[k].ls].mx,tr[tr[k].rs].mx);return;}int ask(int k,int l,int r,int x,int y){if(!k) return 0;if(x<=l&&r<=y) return tr[k].mx;int res=0;if(x<=mid) res=max(res,ask(tr[k].ls,l,mid,x,y));if(y>mid) res=max(res,ask(tr[k].rs,mid+1,r,x,y));return res;}void change(int &k,int l,int r,int p,int w){k=copy(k);if(l==r){tr[k].mx=max(tr[k].mx,w);return;}if(p<=mid) change(tr[k].ls,l,mid,p,w);else change(tr[k].rs,mid+1,r,p,w);pushup(k);}#undef mid }t; int rt[N];set<int>S[N]; set<int>::iterator it; inline int Suf(int k,int w){it=S[k].lower_bound(w);return (it==S[k].end())?0:(*it); } inline int Pre(int k,int w){it=S[k].lower_bound(w);if(it==S[k].begin()) return 0;else{it--;return (*it);} } int fa[N]; int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]); } void merge(int x,int y,int L){//printf("merge: %d %d L=%d\n",x,y,L); x=find(x);y=find(y);if(S[x].size()>S[y].size()) swap(x,y);//printf(" x=%d y=%d\n",x,y);for(int now:S[x]){int pre=Pre(y,now),suf=Suf(y,now);if(pre) t.change(rt[L],1,n,now,pre);if(suf) t.change(rt[L],1,n,suf,now);//printf(" ins:now=%d pre=%d suf=%d\n",now,pre,suf);}for(int now:S[x]){S[y].insert(now);}S[x].clear();fa[x]=y;return; }struct node{int h,id;bool operator < (const node o)const{return h>o.h;} }p[N];signed main(){#ifndef ONLINE_JUDGE//freopen("a.in","w",stdin);//freopen("a.out","w",stdin);#endifn=read();m=read();//printf("%d\n",n);scanf(" %s",s+1);SA();int num(0);for(int i=1;i<=n;i++){fa[i]=i;S[i].insert(i);if(i>1) p[++num]=(node){h[i],i};}sort(p+1,p+1+num);int pl=1;for(int i=n;i>=0;i--){rt[i]=rt[i+1];while(pl<=num&&p[pl].h==i){if(p[pl].id>1){int x=sa[p[pl].id],y=sa[p[pl].id-1];merge(x,y,i);}++pl;}}for(int i=1;i<=m;i++){int l=read(),r=read(),st=0,ed=n;while(st<ed){int mid=(st+ed+1)>>1;if(t.ask(rt[mid],1,n,l,r-mid+1)>=l) st=mid;else ed=mid-1;}printf("%d\n",st);}return 0; } /* 8 1 aabaabba 4 5*/

總結

以上是生活随笔為你收集整理的洛谷P7361:拜神(SA、二分、主席树、启发式合并)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。