CF653F Paper task

题目链接:洛谷


首先我们不考虑本质不同这个限制。

既然不能直接用栈乱搞,我们就可以用一个前缀和的套路了。

我们将(设为1,将)设为-1,记前缀和为$s_i$,则$[i,j]$这一段是回文子串当且仅当

1.$s_j=s_{i-1}$

2.$forall kin [i,j],s_kgeq s_{i-1}$

于是我们枚举$i$,显然$j$要满足第二个性质就肯定不能超过一个上界,这个上界是可以二分的。每次check的时候就判断一下区间最小值,可以用ST表维护。

然后看看本质不同如何做。

这时候我们就要请出SA,求出$sa[]$和$ht[]$之后,枚举$sa[i]$作为左端点,此时必须$jgeq sa[i]+ht[i]$,其中$ht[]$是高度数组,否则就会与前面的字符串重复。

改一改二分的区间就可以了。

 1 #include<bits/stdc++.h>
 2 #define Rint register int
 3 using namespace std;
 4 typedef long long LL;
 5 const int N = 500003;
 6 int n, a[N], m, sa[N], rak[N], tmp[N], c[N], *x = rak, *y = tmp, ht[N];
 7 LL ans;
 8 inline void Qsort(){
 9     for(Rint i = 1;i <= m;i ++) c[i] = 0;
10     for(Rint i = 1;i <= n;i ++) ++ c[x[y[i]]];
11     for(Rint i = 1;i <= m;i ++) c[i] += c[i - 1];
12     for(Rint i = n;i;i --) sa[c[x[y[i]]] --] = y[i];
13 }
14 inline void Ssort(){
15     m = 2;
16     for(Rint i = 1;i <= n;i ++){
17         x[i] = a[i]; y[i] = i;
18     }
19     Qsort();
20     for(Rint w = 1, p;w < n;w <<= 1, m = p){
21         p = 0;
22         for(Rint i = n - w + 1;i <= n;i ++) y[++ p] = i;
23         for(Rint i = 1;i <= n;i ++) if(sa[i] > w) y[++ p] = sa[i] - w;
24         Qsort();
25         swap(x, y);
26         x[sa[1]] = p = 1;
27         for(Rint i = 2;i <= n;i ++)
28             x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + w] == y[sa[i - 1] + w]) ? p : ++ p;
29         if(p >= n) break; 
30     }
31     for(Rint i = 1;i <= n;i ++) rak[sa[i]] = i;
32     int k = 0;
33     for(Rint i = 1;i <= n;i ++){
34         if(rak[i] == 1) continue;
35         int j = sa[rak[i] - 1];
36         if(k) -- k;
37         while(a[j + k] == a[i + k]) ++ k;
38         ht[rak[i]] = k;
39     }
40 }
41 int st[20][N], lg2[N];
42 inline int query(int l, int r){
43     int k = lg2[r - l + 1];
44     return min(st[k][l], st[k][r - (1 << k) + 1]);
45 }
46 vector<int> pos[N << 1];
47 int main(){
48     scanf("%d", &n);
49     for(Rint i = 1;i <= n;i ++){
50         int ch = getchar();
51         while(ch != '(' && ch != ')') ch = getchar();
52         a[i] = (ch == ')') + 1;
53     }
54     Ssort();
55     st[0][0] = n;
56     for(Rint i = 1;i <= n;i ++) st[0][i] = st[0][i - 1] - a[i] * 2 + 3;
57     for(Rint i = 1;i <= n;i ++) pos[st[0][i]].push_back(i);
58     for(Rint i = 1;i <= 19;i ++)
59         for(Rint j = 1;j <= n;j ++)
60             st[i][j] = min(st[i - 1][j], st[i - 1][j + (1 << i - 1)]);
61     lg2[1] = 0;
62     for(Rint i = 2;i <= n;i ++) lg2[i] = lg2[i >> 1] + 1;
63     for(Rint i = 1;i <= n;i ++){
64         if(a[sa[i]] == 2) continue;
65         int l = sa[i] + ht[i], r = n, mid, res = l - 1;
66         while(l <= r){
67             mid = l + r >> 1;
68             if(query(sa[i], mid) >= st[0][sa[i] - 1]){l = mid + 1, res = mid;}
69             else r = mid - 1;
70         }
71         int t = st[0][sa[i] - 1];
72         ans += upper_bound(pos[t].begin(), pos[t].end(), res) - lower_bound(pos[t].begin(), pos[t].end(), sa[i] + ht[i]);
73     }
74     printf("%I64d
", ans);
75 }
76 // nantf tai qiang le
CF653F
原文地址:https://www.cnblogs.com/AThousandMoons/p/10689043.html