很久没写过这东西了,复习一波。

3238: [Ahoi2013]差异

链接

单调栈维护height数组,由于height是递增的,所以维护单调栈中维护每个height出现的次数。(还可以两遍单调栈求一个点是最小值的区间)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13  
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18  
19 const int N = 500005;
20  
21 char s[N];
22 int t1[N], t2[N], c[N], sa[N], rnk[N], height[N], m = 130, n;
23 LL sk[N], cnt[N];
24  
25 void getsa() {
26     int *x = t1, *y = t2, i, p;
27     for (i = 1; i <= m; ++i) c[i] = 0;
28     for (i = 1; i <= n; ++i) x[i] = s[i], c[x[i]] ++;
29     for (i = 1; i <= m; ++i) c[i] += c[i - 1];
30     for (i = 1; i <= n; ++i) sa[c[x[i]]--] = i;
31     for (int k = 1; k <= n; k <<= 1) {
32         p = 0;
33         for (i = n - k + 1; i <= n; ++i) y[++p] = i;
34         for (i = 1; i <= n; ++i) if (sa[i] > k) y[++p] = sa[i] - k;
35         for (i = 1; i <= m; ++i) c[i] = 0;
36         for (i = 1; i <= n; ++i) c[x[y[i]]] ++;
37         for (i = 1; i <= m; ++i) c[i] += c[i - 1];
38         for (i = n; i >= 1; --i) sa[c[x[y[i]]]--] = y[i];
39         swap(x, y);
40         p = 2;
41         x[sa[1]] = 1;
42         for (i = 2; i <= n; ++i) 
43             x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? p - 1 : p ++;
44         if (p > n) break;
45         m = p;
46     }
47 }
48 void getheight() {
49     for (int i = 1; i <= n; ++i) rnk[sa[i]] = i;
50     int k = 0;
51     height[1] = 0;
52     for (int i = 1; i <= n; ++i) {
53         if (rnk[i] == 1) continue;
54         if (k) k --;
55         int j = sa[rnk[i] - 1];
56         while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k ++;
57         height[rnk[i]] = k;
58     }
59 }
60 int main() {
61     scanf("%s", s + 1);
62     n = strlen(s + 1);
63     getsa();
64     getheight();
65     LL ans = 0;
66     for (int i = 1; i <= n; ++i) ans += 1ll * (n - 1) * i;
67     int top = 0;LL now = 0;
68     for (int i = 2; i <= n; ++i) {
69         LL tmp = 1;
70         while (top && sk[top] >= height[i]) {
71             now -= 1ll * cnt[top] * sk[top]; tmp += cnt[top]; top --;
72         }
73         sk[++top] = height[i]; cnt[top] = tmp; now += 1ll * height[i] * tmp;
74         ans -= now * 2;
75     }
76     cout << ans;
77     return 0;
78 }
View Code

相关文章: