后缀数组模板总结

将字符串s的所有后缀排序

洛谷P3809 后缀排序

#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define rep(i,x,n) for(int i=x;i<=n;++i)
#define per(i,n,x) for(int i=n;i>=x;--i)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e6+10;
const int inf=1e9;
char s[N];
int n;
int sa[N],rk[N],wb[N],c[N];
void bd(int m){
    int *x=rk,*y=wb;
    rep(i,1,m) c[i]=0;
    rep(i,1,n) ++c[ x[i]=s[i] ];
    rep(i,2,m) c[i]+=c[i-1];
    per(i,n,1) sa[ c[x[i]]-- ]=i;
    for(int k=1;k<=n;k<<=1){
        int p=0;
        rep(i,n-k+1,n)  y[++p]=i;
        rep(i,1,n) if(sa[i]>k) y[++p]=sa[i]-k;
        rep(i,1,m) c[i]=0;
        rep(i,1,n) ++c[ x[y[i]] ];
        rep(i,2,m) c[i]+=c[i-1];
        per(i,n,1) sa[ c[x[y[i]]]-- ]=y[i],y[i]=0;
        swap(x,y);
        x[sa[1]]=1;
        p=1;
        rep(i,2,n) 
            x[sa[i]] = (y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]) ? p : ++p;
        if(p>=n) break;
        m=p;
    }
}
int main(){
    //ios::sync_with_stdio(false);
    //freopen("in","r",stdin);
    scanf("%s",s+1);
    n=strlen(s+1);
    bd(256);
    rep(i,1,n){
        printf("%d%c",sa[i],i==n?'\n':' ');
    }
    return 0;
}

查询字符串t在字符串s中出现的所有位置

洛谷P3375 KMP字符串匹配

#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define rep(i,x,n) for(int i=x;i<=n;++i)
#define per(i,n,x) for(int i=n;i>=x;--i)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e6+10;
const int inf=1e9;
char s[N],t[N];
int n,m;
int sa[N],rk[N],wb[N],c[N],nex[N];
void bd(int m){
    int *x=rk,*y=wb;
    rep(i,1,m) c[i]=0;
    rep(i,1,n) ++c[ x[i]=s[i] ];
    rep(i,2,m) c[i]+=c[i-1];
    per(i,n,1) sa[ c[x[i]]-- ]=i;
    for(int k=1;k<=n;k<<=1){
        int p=0;
        rep(i,n-k+1,n)  y[++p]=i;
        rep(i,1,n) if(sa[i]>k) y[++p]=sa[i]-k;
        rep(i,1,m) c[i]=0;
        rep(i,1,n) ++c[ x[y[i]] ];
        rep(i,2,m) c[i]+=c[i-1];
        per(i,n,1) sa[ c[x[y[i]]]-- ]=y[i],y[i]=0;
        swap(x,y);
        x[sa[1]]=1;
        p=1;
        rep(i,2,n)
            x[sa[i]] = (y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]) ? p : ++p;
        if(p>=n) break;
        m=p;
    }
}
void get(char *s){
    int n=strlen(s+1);
    for(int i=2,j=0;i<=n;i++){
        while(j&&s[i]!=s[j+1]) j=nex[j];
        if(s[i]==s[j+1]) ++j;
        nex[i]=j;
    }
}
int main(){
    //ios::sync_with_stdio(false);
    //freopen("in","r",stdin);
    scanf("%s",s+1);
    n=strlen(s+1);
    bd(256);
    scanf("%s",t+1);
    m=strlen(t+1);
    int l=1,r=n,L=n+1,R=0;
    while(l<=r){
        int mid=l+r>>1;
        int res=strncmp(t+1,s+sa[mid],m);
        if(res<=0) r=mid-1;
        else l=mid+1;
    }
    L=l;
    l=1,r=n;
    while(l<=r){
        int mid=l+r>>1;
        int res=strncmp(t+1,s+sa[mid],m);
        if(res>=0) l=mid+1;
        else r=mid-1;
    }
    R=r;
    rep(i,1,n) c[i]=0;
    rep(i,L,R) ++c[sa[i]];
    rep(i,1,n) if(c[i]) printf("%d\n",i);
    get(t);
    rep(i,1,m) printf("%d%c",nex[i],i==n?'\n':' ');
    return 0;
}

字符串s的任意两个后缀的最长公共前缀LCP

利用引理\(height[rk[i]]\ge height[rk[i-1]]-1\)\(O(n)\)求出\(height\)数组。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<sstream>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define rep(i,x,n) for(int i=x;i<=n;++i)
#define per(i,n,x) for(int i=n;i>=x;--i)
#define sz(a) int(a.size())
#define rson mid+1,r,p<<1|1
#define pii pair<int,int>
#define lson l,mid,p<<1
#define ll long long
#define pb push_back
#define mp make_pair
#define se second
#define fi first
using namespace std;
const double eps=1e-8;
const int mod=1e9+7;
const int N=1e6+10;
const int inf=1e9;
char s[N],t[N];
int n,m;
int sa[N],rk[N],wb[N],c[N],ht[N],st[N][20];
void bd(int m){
    int *x=rk,*y=wb;
    rep(i,1,m) c[i]=0;
    rep(i,1,n) ++c[ x[i]=s[i] ];
    rep(i,2,m) c[i]+=c[i-1];
    per(i,n,1) sa[ c[x[i]]-- ]=i;
    for(int k=1;k<=n;k<<=1){
        int p=0;
        rep(i,n-k+1,n)  y[++p]=i;
        rep(i,1,n) if(sa[i]>k) y[++p]=sa[i]-k;
        rep(i,1,m) c[i]=0;
        rep(i,1,n) ++c[ x[y[i]] ];
        rep(i,2,m) c[i]+=c[i-1];
        per(i,n,1) sa[ c[x[y[i]]]-- ]=y[i],y[i]=0;
        swap(x,y);
        x[sa[1]]=1;
        p=1;
        rep(i,2,n)
            x[sa[i]] = (y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]) ? p : ++p;
        if(p>=n) break;
        m=p;
    }
}
void get(){
    for(int i=1,k=0;i<=n;i++){
        if(k) --k;
        while(s[i+k]==s[ sa[rk[i]-1] ]+k) ++k;
        ht[rk[i]]=k;
    }
    rep(i,1,n) st[i][0]=ht[i];
    for(int j=1;(1<<j)<=n;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            st[i][j]=min(st[i][j-1],st[i+1<<(j-1)][j-1]);
        }
    }
}
int lcp(int l,int r){
    int k=(int)log2(r-l+1);
    return min(st[l][k],st[r-(1<<k)+1][k]);
}
int main(){
    //ios::sync_with_stdio(false);
    //freopen("in","r",stdin);
    scanf("%s",s+1);
    n=strlen(s+1);
    bd(256);
    get();
    return 0;
}

待更新...

原文链接: https://www.cnblogs.com/xyq0220/p/13308367.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    后缀数组模板总结

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/366524

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午4:44
下一篇 2023年3月2日 下午4:48

相关推荐