后缀数组的原理很好懂,但是蓝书上写的代码,我是真的读不懂啊emmmmmmm
后缀数组的原理
运用了倍增的思想,不断的计算后缀的字典序的大小,关于倍增的图可以看刘汝佳那本书上面的图。
我主要画了一下关于最长公共前缀的原理图。

代码里面的说明
其实sa[], x[]两个表示的东西非常的相似:
sa[i]表示的是:后缀的字典序排在第i位在原来的字符串中的位置为sa[i].
x[i]表示的是:字符串中的位置i在字典序中的大小为x[i].
两者其实是map 的值发生了交换。
其中的一段代码看了好久:
1 2 3 4 5 6 
  | for(int i=n-k; i<n; i++){     y[p++] = i; } for(int i=0; i<n; i++)if(sa[i]>=k) y[p++] = sa[i]-k; 
  | 
先更新的是后面连接’0’的第二维值,然后更新的是后面影响前面的第二维值。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 
  | #include <bits/stdc++.h> using namespace std; const int maxn = 1e4+10; string s; int sa[maxn], x[maxn], y[maxn], c[maxn], n; void build_sa(int m){     int i;     for(int i=0; i<m; i++) c[i] = 0;          for(int i=0; i<n; i++) if(s[i]>='A'&&s[i]<='z')c[x[i]=(s[i]-'A'+1)]++;                             else {c[0]++; x[i] = 0;}     for(int i=1; i<m; i++) c[i] += c[i-1];     for(int i=n-1; i>=0; i--) sa[--c[x[i]]] = i;     for(int k=1; k<=n; k<<=1){         int p = 0;                  for(int i=n-k; i<n; i++){             y[p++] = i;         }                  for(int i=0; i<n; i++)if(sa[i]>=k) y[p++] = sa[i]-k;                           for(int i=0; i<m; i++) c[i] = 0;         for(int i=0; i<n; i++) c[x[y[i]]]++;         for(int i=1; i<m; i++) c[i] += c[i-1];         for(int i=n-1; i>=0; i--){             sa[--c[x[y[i]]]] = y[i];         }         swap(x, y);         p = 1; x[sa[0]] = 0;         for(int i=1; i<n; i++){                          x[sa[i]] = y[sa[i-1]]==y[sa[i]]&&             y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;         }                  if(p>=n) break;         m = p;     } } int main() {     s = "BANANA0";     n = s.length();     build_sa(255);     for(int i=0; i<n; i++){         cout<<sa[i]<<" ";     }     cout<<endl;     return 0; } 
  | 
 
未解决的问题