后缀数组 魔板
為什么一開始要再字符串末尾多算個0呢
因?yàn)楫?dāng)開始分關(guān)鍵字比較的時候 最后要組成兩個
字符所以要多個0 什么你有問我為什么填0
因?yàn)?小啊 先處理唄
雖然
sa是根據(jù)每個字符確定的大小
也就是排布的每個字符的排名
但是在初次求第二關(guān)鍵字排序的時候
可以使用sa的結(jié)論
首先吧sa后面的0排到最前面
那么0的數(shù)量 也就是從n-j到n開區(qū)間 都是0作為第二關(guān)鍵字的區(qū)域
也就是這句話
這一句
for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;是表示
當(dāng)0已經(jīng)排完了
現(xiàn)在再把非0的排進(jìn)去
如何排進(jìn)去呢?
我們看
我們從1-n開區(qū)間枚舉
如果sai大于等于j說明排到第i位的后綴的位置是大于等于j,大于等于
現(xiàn)在的枚舉長度的
那么就把他們放到y(tǒng)
也就是第二關(guān)鍵字排名數(shù)組中 并將其值記錄為本字符串的開始位置sa[i]-j;
由于y數(shù)組中是按照第二關(guān)鍵字排序后存放的開始位置的數(shù)組
那么當(dāng)我按照y從x數(shù)組中把值提取出來付給wv數(shù)組時 就相當(dāng)于
把要比較的長度為2的倍增一倍的數(shù)組放到wv中去了
接下來就用下面的四個for循環(huán)來按第一關(guān)鍵字對合并后的字符串進(jìn)行排序,最后更新sa道理同上面對字符串第一個字符進(jìn)行排序的四個for循環(huán)。
1:盛放j=1 長度為2 由于是按照低位排過序后的數(shù)組放入的wv 而wv存放的是第一關(guān)鍵字的值 為后續(xù)排序做準(zhǔn)備
2:按照第一關(guān)鍵字的順序?qū)⑵溲b桶標(biāo)記
3:按照第一關(guān)鍵字的順序計算前綴和
4: 對于每個wv 是先按照第二關(guān)鍵字排序順序裝入的ws 也就是基數(shù)排序的本質(zhì)
此時在2句又按照第一關(guān)鍵字的值(存儲的是第一關(guān)鍵字的值)排好了序
每次– 逆序處理
此時得到的sa數(shù)組 就是一個在以第一二關(guān)鍵字合并的情況下按照其大小按照加上第一關(guān)鍵字的新順序從高到低
講y數(shù)組(記錄的是初始位置)的值付給sa
表示字符串排序第i個位于y[i]
最后再來看下cmp函數(shù)的作用
如果y也就是原來的x數(shù)組下a位置的和b位置的相等 并且第二關(guān)鍵字也相等
那么就會返回1
返回1就會讓這段字符的實(shí)質(zhì)排名為p-1 返回0表示不相等那么就說明兩段不相等
讓其等于p 則兩段字符的排名相同
最終的p值 就代表我一共有排到了幾 其中有可能有排名相等的項
那么這個p也就是其中下一循環(huán)的m值 也就是下一次循環(huán)
其中每個單關(guān)鍵字的排名不會超過m 存儲到x數(shù)組中
魔板:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; typedef long long ll; int n,m; int *t,sa[1010],a[1010],b[1010],ms[1010],mv[1010]; char aa[50]; void LSD(int n,int *x,int *y,int *Ws,int *wv){m = 130;for(int i=0;i<m;i++)Ws[i]=0;for(int i=0;i<n;i++)Ws[x[i]=aa[i]]++;for(int i=1;i<m;i++)Ws[i]+=Ws[i-1];for(int i=n-1;i>=0;i--)sa[--Ws[x[i]]]=i;for(int p=1,m,j=1;p<n;j<<=1,m=p){p=0;for(int i=n-j;i<n;i++)y[p++]=i;for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;for(int i=0;i<n;i++)wv[i]=x[y[i]];for(int i=0;i<m;i++)Ws[i]=0;for(int i=0;i<n;i++)Ws[wv[i]]++;for(int i=1;i<m;i++)Ws[i]+=Ws[i-1];for(int i=n-1;i>=0;i--)sa[--Ws[wv[i]]]=y[i];int i;for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)x[sa[i]] =(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]) ?p-1:p++;}return; } int main() {scanf("%s",aa);LSD(strlen(aa)+1,a,b,ms,mv);for(int i=0;i<strlen(aa);i++)printf("%d ",sa[i]);puts("");return 0; }總結(jié)
- 上一篇: 单点登录系统cas资料汇总
- 下一篇: autocad不能画图_学了这些CAD技