SuffixArray.cpp 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. // Suffix array construction in O(L log^2 L) time. Routine for
  2. // computing the length of the longest common prefix of any two
  3. // suffixes in O(log L) time.
  4. // INPUT: string s
  5. // OUTPUT: array suffix[] such that suffix[i] = index (from 0 to L-1)
  6. // of substring s[i...L-1] in the list of sorted suffixes.
  7. // That is, if we take the inverse of the permutation suffix[],
  8. // we get the actual suffix array.
  9. struct SuffixArray {
  10. const int L;
  11. string s;
  12. VVI P;
  13. vector<pair<PII,int> > M;
  14. SuffixArray(const string &s) : L(s.length()), s(s), P(1, VI(L, 0)), M(L) {
  15. for(int i = 0; i < L; i++)
  16. P[0][i] = int(s[i]);
  17. for(int skip = 1, level = 1; skip < L; skip *= 2, level++) {
  18. P.push_back(VI(L, 0));
  19. for(int i = 0; i < L; i++)
  20. M[i] = make_pair(make_pair(P[level-1][i], i + skip < L ? P[level-1][i + skip] : -1000), i);
  21. sort(M.begin(), M.end());
  22. for(int i = 0; i < L; i++)
  23. P[level][M[i].second] = (i > 0 && M[i].first == M[i-1].first) ? P[level][M[i-1].second] : i;
  24. }
  25. }
  26. VI GetSuffixArray() { return P.back(); }
  27. // returns the length of the longest common prefix of s[i...L-1] and s[j...L-1]
  28. int LongestCommonPrefix(int i, int j) {
  29. int len = 0;
  30. if(i == j) return L - i;
  31. for(int k = P.size() - 1; k >= 0 && i < L && j < L; k--) {
  32. if (P[k][i] == P[k][j]) {
  33. i += 1 << k;
  34. j += 1 << k;
  35. len += 1 << k;
  36. }
  37. }
  38. return len;
  39. }
  40. };
  41. int test() {
  42. // bobocel is the 0'th suffix
  43. // obocel is the 5'th suffix
  44. // bocel is the 1'st suffix
  45. // ocel is the 6'th suffix
  46. // cel is the 2'nd suffix
  47. // el is the 3'rd suffix
  48. // l is the 4'th suffix
  49. SuffixArray suffix("bobocel");
  50. VI v = suffix.GetSuffixArray();
  51. // Expected output: 0 5 1 6 2 3 4
  52. // 2
  53. for(int i = 0; i < v.size(); i++)
  54. cout << v[i] << " ";
  55. cout << endl;
  56. cout << suffix.LongestCommonPrefix(0, 2) << endl;
  57. }