我編寫了一個後綴數組實現,並在我的實現中發現了一個問題。具體我已經輸出的第一少數後綴數組居此string的RA[0..7]
(長度= 10^5)並具有下面的輸出:後綴數組實現錯誤
80994
84360
87854
91517
95320
99277
83068
但是正確的一個必須是(一切由23移位):
81017
84383
87877
91540
95343
99300
83091
我知道如何解決它的兩種方法,但我不知道它爲什麼起作用。
第一種方式是添加S[N++] = '$';
到buildSA()
函數的頂部(則輸出比正確的1少,但它並不重要)
我還發現另一種解決方案通過減小MAX_N恆定到1e5 + 10!
這對我來說太神奇了,我真的需要知道爲什麼發生這個錯誤,因爲我不想再次發生這個錯誤。
#include <cstdio>
#include <cstring>
#include <algorithm>
using std::max;
const int MAX_N = 2e5 + 10;
int SA[MAX_N]; // The ith element is the index of the suffix
int RA[MAX_N]; // The rank of the suffix at i
int tmp[MAX_N]; // A temporary array
int B[MAX_N]; // An array for the buckets
int N;
char S[MAX_N];
void bucketSort(int k){
int i, m = max(256, N);
for(i = 0; i < m; i++)
B[i] = 0;
for(i = 0; i < N; i++)
B[i + k < N ? RA[i + k] : 0] ++;
for(i = 1; i < m; i++)
B[i] += B[i - 1];
for(i = N - 1; i >= 0; i--)
tmp[--B[SA[i] + k < N ? RA[SA[i] + k] : 0]] = SA[i];
for(i = 0; i < N; i++)
SA[i] = tmp[i];
}
void buildSA(){
for(int i = 0; i < N; i++){
SA[i] = i;
RA[i] = S[i];
}
for(int k = 1; k < N; k <<= 1){
bucketSort(k);
bucketSort(0);
int norder = 0;
tmp[SA[0]] = 0;
for(int i = 1; i < N; i++){
if(RA[SA[i]] == RA[SA[i - 1]] && RA[SA[i] + k] == RA[SA[i - 1] + k])
{} else norder++;
tmp[SA[i]] = norder;
}
for(int i = 0; i < N; i++)
RA[i] = tmp[i];
if(norder == N)
break;
}
}
void printSA(){
for(int i = 0; i < N; i++){
printf("%d: %s\n", SA[i], S + SA[i]);
}
}
int main(){
scanf("%s", S);
N = strlen(S);
buildSA();
for(int i = 0; i < 7; i++){
printf("%d\n",RA[i]);
}
return 0;
}
我沒有被問到錯誤的問題(一些SOers會這樣做),但您必須通過查找觸發它的*最小可能*輸入來做出努力。 –
(尋找觸發錯誤的小輸入是您在*嘗試自行修復它的過程中應該做的第一件事情。) –
隨機測試有助於查找小問題輸入。 –