zoukankan      html  css  js  c++  java
  • 后缀数组模板总结

    将字符串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?'
    ':' ');
    	}
    	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
    ",i);
        get(t);
        rep(i,1,m) printf("%d%c",nex[i],i==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;
    }
    

    待更新...

  • 相关阅读:
    VS2005 中关于“LC.EXE已退出,代码为 1”的错误解决方法。
    由于目标机器积极拒绝,无法连接。
    What is Android?
    利用批处理文件和任务计划实现Oracle数据库的自动备份
    就差了一点点....
    由Login.aspx引发编译器错误的解决方法
    都是补丁惹的祸...
    终于结束了
    GIS当然可以很酷
    rar.exe命令行参数与示例
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13308367.html
Copyright © 2011-2022 走看看