後綴數組

膜拜大佬:https://www.cnblogs.com/victorique/p/8480093.html#autoid-1-3-1

題目:https://www.luogu.org/problemnew/show/P3809

簡單的後綴排序

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1000500

using namespace std;
int x[N];//備用串 
int sa[N];//每個字符串首字符當排名爲i時在輸入串中的位置
int y[N]; // 排名爲i的子串首字符(sa[i]所代表的字串的第k個字符)在原串的位置 
int c[N];//先記錄各個字符的個數,求前綴和即表示,用來記錄每個字符最晚出現的排名位置 
int wt[30];
int n,m=122;//串長度 z的ASCII值爲122 
char s[N];//輸入串 



void slove(){
   for(int i=1;i<=n;++i) ++c[x[i]=s[i]];//備份輸入串同時記錄每個字符的個數
   // c[a]=3;c[b]=7; 
   for(int i=2;i<=m;++i) c[i]+=c[i-1];// 記錄每個字符最晚出現的排名的位置
   // c[a]=3;c[b]=7;
   for(int i=n;i>=1;--i) sa[c[x[i]]--]=i;//記錄每個字符串首字符當排名爲i時在輸入串中的位置 
   // 位置 1 2 3 4 5
   //      a b a b a
   // 排名 1 4 2 5 3  ---> sa[1]=1;sa[2]=3;sa[3]=5;sa[4]=2;sa[5]=4;
   
   for(int k=1;k<=n;k<<=1){
   	 int num=0;
   	 for(int i=n-k+1;i<=n;++i) y[++num]=i;//輸入串的最後k個字符所在位置一定是y[1~k] 所在位置
		    //  k==1時  y[1]=5;   k==2時 y[1]=4,y[2]=5; 
	//y[]在每次循環中所代表的是 當關鍵字按照每個子串第k個字符所排序後第i位該字符在原串中的位置 
   	//並不是所有的子串都有第k個字符 要保證sa[i]>k 
	//y[]中排名後n-k位第i位的字符所在的位置其實就是sa[]中排名第i的位置減k ; 
	//k==1時   sa[1]=1;sa[2]=3;sa[3]=5;sa[4]=2;sa[5]=4
    //                  y[2]=2; y[3]=4; y[4]=1; y[5]=3;
	  for(int i=1;i<=n;++i){//將剩下的字符排序 
   	 	   if(sa[i]>k) y[++num]=sa[i]-k;
	   }
	   
	   for(int i=1;i<=m;++i) c[i]=0;
	   for(int i=1;i<=n;++i) ++c[x[i]];
	   for(int i=2;i<=m;++i) c[i]+=c[i-1]; //c[]在之前的代碼中更改了需要重新賦值
	   
	   for(int i=n;i>=1;--i){
	   	//跟第17行代碼有異曲同工之妙 只是將用來排名的字符由首字符換成了子串的第k位 
	   	//此時sa[]已更新爲以子串前k+1個字符重新排序之後的結果 
	   	  sa[c[x[y[i]]]--]=y[i];y[i]=0;	 
	   } 
	   
	   swap(x,y);//因爲需要用x[]來更新x[],而此時y[]串相當於爲空  剛好可以用
	   //此時的y相當於輸入串的備用串 
	   x[sa[1]]=1;
	   num=1;
	   for(int i=2;i<=n;++i) 
	    x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num; 
	   //當sa[]位置上所代表的字符都不同時結束循環 
	   if(num==n) break;
	   m=num; 
   } 
   for(int i=1;i<=n;i++)cout<<sa[i]<<" ";
}

int main(){
	gets(s+1);//排名從1開始 
	n=strlen(s+1);
	slove();
	return 0;
}
/*
ababa
*/

emmm   lcp還沒看懂 明天繼續研究 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章