首先把后缀数组和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 }
View Code

 

posted on 2015-05-03 22:17  Xs酱~  阅读(188)  评论(0编辑  收藏  举报