首先把后缀数组和height数组都搞出来。。。
然后用两个单调栈维护$[l, r]$表示对于一个点$x$,满足$height[x] \le height[l..x] \ \&\&\ height[x] < height[x..r]$的最小的$l$和最大的$r$
这样子就可以保证不会重复计算了
1 /************************************************************** 2 Problem: 3238 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:4496 ms 7 Memory:20336 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 13 using namespace std; 14 typedef long long ll; 15 const int N = 5e5 + 5; 16 17 int a[N], len; 18 int sa[N], rank[N], height[N]; 19 20 inline void Sort(int *a, int *b, int *c, int n, int m) { 21 static int i, sum[N]; 22 for (i = 0; i <= m; ++i) sum[i] = 0; 23 for (i = 0; i < n; ++i) ++sum[c[a[i]]]; 24 for (i = 1; i <= m; ++i) sum[i] += sum[i - 1]; 25 for (i = n - 1; ~i; --i) 26 b[--sum[c[a[i]]]] = a[i]; 27 } 28 29 void make_sa(int *s) { 30 int i, j; 31 static int x[N], y[N]; 32 for (i = 0; i < len; ++i) x[i] = s[i], rank[i] = i; 33 Sort(rank, sa, x, len, 30); 34 rank[sa[0]] = 1; 35 for (i = 1; i < len; ++i) 36 rank[sa[i]] = rank[sa[i - 1]] + (x[sa[i]] != x[sa[i - 1]]); 37 for (i = 1; i <= len; i <<= 1) { 38 for (j = 0; j < len; ++j) 39 x[j] = rank[j], y[j] = j + i < len ? rank[j + i] : 0, sa[j] = j; 40 Sort(sa, rank, y, len, len), Sort(rank, sa, x, len, len); 41 rank[sa[0]] = 1; 42 for (j = 1; j < len; ++j) 43 rank[sa[j]] = rank[sa[j - 1]] + (x[sa[j]] != x[sa[j - 1]] || y[sa[j]] != y[sa[j - 1]]); 44 if (rank[sa[len - 1]] == len) return; 45 } 46 } 47 48 void make_height() { 49 int i, j; 50 for (i = j = 0; i < len; ++i) { 51 if (j) --j; 52 if (rank[i] != 1) 53 while (a[i + j] == a[sa[rank[i] - 2] + j]) ++j; 54 height[rank[i]] = j; 55 } 56 } 57 58 ll work() { 59 int i; 60 ll res; 61 static int s[N], top, l[N], r[N]; 62 for (res = 0, i = 1; i <= len; ++i) res += 1ll * i * (len - 1); 63 for (s[top = 0] = 0, i = 1; i <= len; ++i) { 64 while (height[i] <= height[s[top]] && top) --top; 65 l[i] = s[top] + 1; 66 s[++top] = i; 67 } 68 for (s[top = 0] = len + 1, i = len; i; --i) { 69 while (height[i] < height[s[top]] && top) --top; 70 r[i] = s[top] - 1; 71 s[++top] = i; 72 } 73 for (i = 1; i <= len; ++i) 74 res -= 2ll * (i - l[i] + 1) * (r[i] - i + 1) * height[i]; 75 return res; 76 } 77 78 int main() { 79 int i; 80 char ch; 81 for (len = 0; ;) { 82 ch = getchar(); 83 if ('a' <= ch && ch <= 'z') a[len++] = ch - 'a' + 1; 84 else break; 85 } 86 make_sa(a); 87 make_height(); 88 printf("%lld\n", work()); 89 return 0; 90 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen