學習筆記----字尾陣列
論文裡面寫的比較清晰了,但是程式碼裡面沒有解釋,又從網上找到了一份程式碼的註釋,解釋的挺好的
地址:http://www.cnblogs.com/Lyush/p/3233573.html
這裡是程式碼模板:
倍增演算法實現的,效率很高。
const int maxn = 10010;
int wa[maxn], wb[maxn], wv[maxn], ws1[maxn];
int cmp(int *r, int a, int b, int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int *r,int *sa,int n,int m)
{
int i, j, p, *x = wa,*y = wb;
// 下面四行是對第一個字母的一個基數排序:基數排序其實就是記錄前面有多少個位置被佔據了
for(i = 0; i<m; i++) ws1[i]=0; // 將統計字元數量的陣列清空
for(i = 0; i<n; i++) ws1[x[i]=r[i]]++; // 統計各種字元的個數
for(i = 1; i<m; i++) ws1[i]+=ws1[i-1]; // 進行一個累加,因為前面的小字符集對後面字元的排位有位置貢獻
for(i = n-1; i>=0; i--) sa[--ws1[x[i]]]=i; // 根據位置來排序,sa[x] = i,表示i位置排在第x位
// wa[x[i]]就是字符集0-x[i]共有多少字元佔據了位置,減去自己的一個位置剩下的就是自己的排名了,排名從0開始
// 排名過程中主要的過程是對於處於相同字元的字元的排序,因為改變wa[x[i]]值得只會是本身,小於該字元的貢獻值
// 是不變的,對於第一個字元相同的依據是位置關係,在後面將看到通過第二個關鍵字來確定相同字元的先後關係
// 這以後的排序都是通過兩個關鍵字來確定一個串的位置,也即倍增思想
// 通過將一個串分解成兩部分,而這兩部分的位置關係我們都已經計算出來
for(j = 1, p = 1; p<n; j*=2, m=p)
{
for(p = 0, i = n-j; i<n; i++) y[p++]=i; // 列舉的串是用於與i位置的串進行合併,由於i較大,因為匹配的串為空串
// 由於列舉的是長度為j的串,那麼i位置開始的串將湊不出這個長度的串,因此第二關鍵字應該最小,這其中位置靠前的較小
for(i = 0; i<n; i++)
if(sa[i]>=j) y[p++]=sa[i]-j; // sa[i]-j開頭的串作為第二關鍵字與編號為sa[i]的串匹配,sa[i]<j的串不用作為第二關鍵字來匹配
for(i = 0; i<n; i++) wv[i]=x[y[i]]; // 取出這些位置的第一關鍵字
for(i = 0; i<m; i++) ws1[i]=0;
for(i = 0; i<n; i++) ws1[wv[i]]++;
for(i = 1; i<m; i++) ws1[i]+=ws1[i-1];
for(i = n-1; i>=0; i--) sa[--ws1[wv[i]]]=y[i]; // 按照第二關鍵字進行第一關鍵字的基數排序
for(swap(x,y),p=1,x[sa[0]]=0,i=1; i<n; i++) // 對排好序的sa陣列進行一次字符集縮小、常數優化
x[sa[i]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
return;
}
int rank[maxn],height[maxn];
void calheight(int *r,int *sa,int n) // 這裡的n是原串的本來長度,即不包括新增的0
{
int i,j,k=0;
for(i = 1; i<=n; i++) rank[sa[i]]=i; // 有字尾陣列得到名次陣列,排名第0的字尾一定是新增的0
for(i = 0; i<n; height[rank[i++]]=k) // 以 i 開始的字尾總能夠從以 i-1 開始的字尾中繼承 k-1 匹配項出來
for(k?k--:0, j=sa[rank[i]-1]; r[i+k] == r[j+k]; k++); // 進行一個暴力的匹配,但是整個演算法的時間複雜度還是O(n)的
return;
}
int main()
{
return 0;
}
模板:
const int maxn = 10010;
int wa[maxn], wb[maxn], wv[maxn], ws1[maxn];
int cmp(int *r, int a, int b, int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int *r,int *sa,int n,int m)
{
int i, j, p, *x = wa,*y = wb;
for(i = 0; i<m; i++) ws1[i]=0;
for(i = 0; i<n; i++) ws1[x[i]=r[i]]++;
for(i = 1; i<m; i++) ws1[i]+=ws1[i-1];
for(i = n-1; i>=0; i--) sa[--ws1[x[i]]]=i;
for(j = 1, p = 1; p<n; j*=2, m=p)
{
for(p = 0, i = n-j; i<n; i++) y[p++]=i;
for(i = 0; i<n; i++)
if(sa[i]>=j) y[p++]=sa[i]-j;
for(i = 0; i<n; i++) wv[i]=x[y[i]];
for(i = 0; i<m; i++) ws1[i]=0;
for(i = 0; i<n; i++) ws1[wv[i]]++;
for(i = 1; i<m; i++) ws1[i]+=ws1[i-1];
for(i = n-1; i>=0; i--) sa[--ws1[wv[i]]]=y[i];
for(swap(x,y),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++;
}
return;
}
int rank[maxn],height[maxn];
void calheight(int *r,int *sa,int n)
{
int i,j,k=0;
for(i = 1; i<=n; i++) rank[sa[i]]=i;
for(i = 0; i<n; height[rank[i++]]=k)
for(k?k--:0, j=sa[rank[i]-1]; r[i+k] == r[j+k]; k++);
return;
}
int main()
{
return 0;
}
相關文章
- 字尾陣列 學習筆記陣列筆記
- 字尾陣列學習筆記陣列筆記
- 【筆記】字尾陣列筆記陣列
- 字尾陣列複習陣列
- 字尾自動機學習筆記筆記
- JS陣列學習筆記JS陣列筆記
- 字尾陣列模板陣列
- 字尾陣列 SA陣列
- 字尾陣列,SA陣列
- 學習筆記——陣列方法整理筆記陣列
- Java學習筆記之陣列Java筆記陣列
- 學習筆記----樹狀陣列筆記陣列
- swift 學習筆記之陣列Swift筆記陣列
- 字尾陣列(後續)陣列
- 字尾陣列詳解陣列
- Java學習筆記——陣列練習(七)Java筆記陣列
- Java 學習筆記 二維陣列和物件陣列Java筆記陣列物件
- 【C#學習筆記】陣列使用C#筆記陣列
- OI loves Algorithm——字尾陣列Go陣列
- Perl學習筆記(五)——關聯陣列筆記陣列
- Object C學習筆記11-陣列Object筆記陣列
- JavaScript 學習筆記 - 多維陣列變為一維陣列JavaScript筆記陣列
- 飛機的 PHP 學習筆記五:陣列PHP筆記陣列
- JavaScript學習筆記(二)——函式和陣列JavaScript筆記函式陣列
- 【numpy學習筆記】陣列的切片,索引,迭代筆記陣列索引
- Solidity語言學習筆記————12、陣列Solid筆記陣列
- Swift學習筆記(二十)——陣列的基本操作Swift筆記陣列
- BZOJ2882: 工藝(字尾陣列)陣列
- POJ 3581-Sequence(字尾陣列)陣列
- POJ 1743 Musical Theme(字尾陣列)陣列
- ES6學習筆記(二)【數值,陣列】筆記陣列
- numpy學習筆記 – numpy陣列的常見用法筆記陣列
- Java學習筆記【1】陣列的宣告和建立Java筆記陣列
- PHP學習筆記6:表示式&多維陣列PHP筆記陣列
- 【Java學習筆記之五】java陣列詳解Java筆記陣列
- Go 語言學習筆記之陣列與切片Go筆記陣列
- 【numpy學習筆記】陣列的儲存和下載筆記陣列
- 【大話儲存】學習筆記(6章), 磁碟陣列筆記陣列