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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

后缀数组 魔板

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

為什么一開始要再字符串末尾多算個0呢
因為當開始分關鍵字比較的時候 最后要組成兩個
字符所以要多個0 什么你有問我為什么填0
因為0小啊 先處理唄
雖然
sa是根據每個字符確定的大小
也就是排布的每個字符的排名
但是在初次求第二關鍵字排序的時候
可以使用sa的結論
首先吧sa后面的0排到最前面
那么0的數量 也就是從n-j到n開區間 都是0作為第二關鍵字的區域
也就是這句話

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;

是表示
當0已經排完了
現在再把非0的排進去
如何排進去呢?
我們看
我們從1-n開區間枚舉
如果sai大于等于j說明排到第i位的后綴的位置是大于等于j,大于等于
現在的枚舉長度的
那么就把他們放到y
也就是第二關鍵字排名數組中 并將其值記錄為本字符串的開始位置sa[i]-j;

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

由于y數組中是按照第二關鍵字排序后存放的開始位置的數組
那么當我按照y從x數組中把值提取出來付給wv數組時 就相當于
把要比較的長度為2的倍增一倍的數組放到wv中去了
接下來就用下面的四個for循環來按第一關鍵字對合并后的字符串進行排序,最后更新sa道理同上面對字符串第一個字符進行排序的四個for循環。

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 由于是按照低位排過序后的數組放入的wv 而wv存放的是第一關鍵字的值 為后續排序做準備
2:按照第一關鍵字的順序將其裝桶標記
3:按照第一關鍵字的順序計算前綴和
4: 對于每個wv 是先按照第二關鍵字排序順序裝入的ws 也就是基數排序的本質
此時在2句又按照第一關鍵字的值(存儲的是第一關鍵字的值)排好了序
每次– 逆序處理
此時得到的sa數組 就是一個在以第一二關鍵字合并的情況下按照其大小按照加上第一關鍵字的新順序從高到低
講y數組(記錄的是初始位置)的值付給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函數的作用
如果y也就是原來的x數組下a位置的和b位置的相等 并且第二關鍵字也相等
那么就會返回1
返回1就會讓這段字符的實質排名為p-1 返回0表示不相等那么就說明兩段不相等
讓其等于p 則兩段字符的排名相同
最終的p值 就代表我一共有排到了幾 其中有可能有排名相等的項
那么這個p也就是其中下一循環的m值 也就是下一次循環
其中每個單關鍵字的排名不會超過m 存儲到x數組中

魔板:

#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; }

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。