fork(1) download
  1. #include <string>
  2. #include <vector>
  3. #include <iostream>
  4. #include <algorithm>
  5. using namespace std;
  6. int doubles, lengths, dat[100002], tmp[100002], rank_[100002];
  7. bool compare_suffix(int i, int j) {
  8. if (dat[i] == dat[j]) {
  9. int ri = (i + doubles <= lengths ? dat[i + doubles] : -1);
  10. int rj = (j + doubles <= lengths ? dat[j + doubles] : -1);
  11. return ri < rj;
  12. }
  13. return dat[i] < dat[j];
  14. }
  15. vector<int> suffix_array(string S) {
  16. lengths = S.size();
  17. vector<int> arrays(lengths + 1);
  18. for (int i = 0; i <= lengths; i++) {
  19. arrays[i] = i;
  20. dat[i] = i < lengths ? S[i] : -1;
  21. }
  22. for (doubles = 1; doubles <= lengths; doubles <<= 1) {
  23. sort(arrays.begin(), arrays.begin() + lengths + 1, compare_suffix);
  24. tmp[arrays[0]] = 0;
  25. for (int i = 1; i <= lengths; i++) tmp[arrays[i]] = tmp[arrays[i - 1]] + (compare_suffix(arrays[i - 1], arrays[i]) ? 1 : 0);
  26. for (int i = 0; i <= lengths; i++) dat[i] = tmp[i];
  27. }
  28. return arrays;
  29. }
  30. vector<int> lcp(string s, vector<int> sa) {
  31. vector<int> ret; ret.resize(lengths + 1);
  32. for (int i = 0; i <= lengths; i++) rank_[sa[i]] = i;
  33. int h = 0; ret[0] = 0;
  34. for (int i = 0; i < lengths; i++) {
  35. int j = sa[rank_[i] - 1];
  36. if (h > 0) h--;
  37. for (; j + h < lengths && i + h < lengths; h++) {
  38. if (s[j + h] != s[i + h]) break;
  39. }
  40. ret[rank_[i] - 1] = h;
  41. }
  42. return ret;
  43. }
  44. string s, f; long long ret = 0;
  45. int main() {
  46. cin >> s;
  47. vector<int> v1 = suffix_array(s);
  48. vector<int> v2 = lcp(s, v1);
  49. for (int i = 1; i <= s.size(); i++) {
  50. ret += 1LL * (lengths - v1[i]) * (lengths - v1[i] + 1) / 2 - 1LL * v2[i] * (v2[i] + 1) / 2;
  51. }
  52. cout << ret << endl;
  53. return 0;
  54. }
  55.  
Success #stdin #stdout 0s 4636KB
stdin
atcoder
stdout
84