日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

后缀数组 魔板

發(fā)布時間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 后缀数组 魔板 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

為什么一開始要再字符串末尾多算個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(p=0,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;

是表示
當(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;

for(i=0;i<n;i++) wv[i]=x[y[i]];

由于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)。

for(i=0;i<m;i++) ws[i]=0;//將新的桶清0 1for(i=0;i<n;i++) ws[wv[i]]++;//2for(i=1;i<m;i++) ws[i]+=ws[i-1];//3for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];//4

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]

for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}一個cmp

最后再來看下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é)

以上是生活随笔為你收集整理的后缀数组 魔板的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。