大意是给出一个只包含‘(‘和‘)‘的括号串,求有多少不同的子串是合法的括号串
解法:对于每一个后缀,需要能够求出这个后缀有多少前缀是合法的括号串,这个可以用O(log n)复杂度的二分来解决。注意,二分的范围并不是整个后缀,因为如果将‘(‘视作+1, ‘)‘视作-1,则一个合法的括号串必须时刻不能小于0。所以可以在ST表上二分出合法范围,在这个范围内去统计有多少合法串(即‘(‘与‘)‘正负相消)。求出一个区间内有多少数字值为x可以对一个保存值和位置的pair数组排序后二分。
那么剩下的问题就是如何去重,由于height数组中记录的是排名相邻的两个后缀的最长公共前缀LCP,那么每一次统计只要根据这个信息减去相应重复统计的数量即可。
下面的代码中统计了两次num,是直接对上述思路的实现,其实是可以合并的。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string.h> 6 #include <stdio.h> 7 #include <math.h> 8 #include <queue> 9 #include <stack> 10 #include <map> 11 #include <set> 12 13 using namespace std; 14 15 16 const int N=500000+100; 17 char s[N]; 18 int sum[N]; 19 vector< pair<int,int> >v; 20 21 int preLog2[N]; 22 struct SparseTable { 23 #define T int 24 #define MAXN N 25 static T MIN(T a,T b){return a<b?a:b;} 26 static T MAX(T a,T b){return a>b?a:b;} 27 SparseTable() { 28 if (!preLog2[2]){ 29 preLog2[1]=0; 30 for (int i=2;i<MAXN;i++) 31 preLog2[i]=preLog2[i>>1]+1; 32 } 33 } 34 T dp[MAXN][21]; 35 T (*cmp) (T,T); 36 void setMin(){cmp=MIN;} 37 void setMax(){cmp=MAX;} 38 void init(int n,T *val) { 39 for (int i=0;i<n;i++) 40 dp[i][0]=val[i]; 41 for (int j=1;(1<<j)<=n;j++) { 42 int k=1<<(j-1); 43 for (int i=0;i+k<n;i++) 44 dp[i][j]=cmp(dp[i][j-1],dp[i+k][j-1]); 45 } 46 } 47 T query(int a,int b) { 48 if (a>b) swap(a,b); 49 int k=preLog2[b-a+1]; 50 return cmp(dp[a][k],dp[b-(1<<k)+1][k]); 51 } 52 #undef MAXN 53 #undef T 54 }tab; 55 struct SuffixArray { 56 int wa[N], wb[N], cnt[N], wv[N]; 57 int rk[N], height[N]; 58 int sa[N]; 59 bool cmp(int r[], int a, int b, int l) { 60 return r[a] == r[b] && r[a+l] == r[b+l]; 61 } 62 void calcSA(char r[], int n, int m) { 63 int i, j, p, *x = wa, *y = wb; 64 for (i = 0; i < m; ++i) cnt[i] = 0; 65 for (i = 0; i < n; ++i) cnt[x[i]=r[i]]++; 66 for (i = 1; i < m; ++i) cnt[i] += cnt[i-1]; 67 for (i = n-1; i >= 0; --i) sa[--cnt[x[i]]] = i; 68 for (j = 1, p = 1; p < n; j *= 2, m = p) { 69 for (p = 0, i = n - j; i < n; ++i) y[p++] = i; 70 for (i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j; 71 for (i = 0; i < n; ++i) wv[i] = x[y[i]]; 72 for (i = 0; i < m; ++i) cnt[i] = 0; 73 for (i = 0; i < n; ++i) cnt[wv[i]]++; 74 for (i = 1; i < m; ++i) cnt[i] += cnt[i-1]; 75 for (i = n-1; i >= 0; --i) sa[--cnt[wv[i]]] = y[i]; 76 for (swap(x, y), p = 1, x[sa[0]] = 0, i = 1; i < n; ++i) 77 x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++; 78 } 79 } 80 void calcHeight(char r[], int n) { 81 int i, j, k = 0; 82 for (i = 0; i <= n; ++i) rk[sa[i]] = i; 83 for (i = 0; i < n; height[rk[i++]] = k) 84 for (k?k--:0, j = sa[rk[i]-1]; r[i+k] == r[j+k]; k++); 85 } 86 int lcp(int a,int b,int len) { 87 if (a==b) return len-a; 88 int ra=rk[a],rb=rk[b]; 89 if (ra>rb) swap(ra,rb); 90 return queryST(ra+1,rb); 91 } 92 int st[N][24]; 93 int preLog2[N]; 94 void initST(int n) { 95 for (int i=1;i<=n; i++) 96 st[i][0]=height[i]; 97 for (int j=1;(1<<j)<=n; j++) { 98 int k=1<<(j-1); 99 for (int i=1; i+k<=n; i++) 100 st[i][j]=min(st[i][j-1],st[i+k][j-1]); 101 } 102 preLog2[1]=0; 103 for(int i=2;i<=n;i++){ 104 preLog2[i]=preLog2[i>>1]+1; 105 } 106 } 107 int queryST(int a,int b) { 108 if (a>b) swap(a,b); 109 int dis=b-a+1; 110 int k=preLog2[dis]; 111 return min(st[a][k],st[b-(1<<k)+1][k]); 112 } 113 void solve(int n) { 114 long long ret=0; 115 for (int i=1;i<=n;i++) { 116 if (s[sa[i]]==‘)‘) continue; 117 int l=sa[i],h=n-1,p=n; 118 while (l<=h) { 119 int m=(l+h)>>1; 120 if (tab.query(l,m)<sum[sa[i]]-1) { 121 p=m; 122 h=m-1; 123 } 124 else 125 l=m+1; 126 } 127 p--; 128 int num=upper_bound(v.begin(),v.end(),make_pair(sum[sa[i]]-1,p))-lower_bound(v.begin(),v.end(),make_pair(sum[sa[i]]-1,sa[i])); 129 ret+=num; 130 int preR=min(sa[i]+height[i]-1,p); 131 num=upper_bound(v.begin(),v.end(),make_pair(sum[sa[i]]-1,preR))-lower_bound(v.begin(),v.end(),make_pair(sum[sa[i]]-1,sa[i])); 132 ret-=num; 133 } 134 printf("%I64d\n",ret); 135 } 136 }suf; 137 138 int main() { 139 int n; 140 scanf("%d",&n); 141 scanf("%s",s); 142 sum[0]=(s[0]==‘(‘)?1:-1; 143 for (int i=1;i<n;i++) 144 sum[i]=sum[i-1]+((s[i]==‘(‘)?1:-1); 145 for (int i=0;i<n;i++) { 146 v.push_back(make_pair(sum[i],i)); 147 } 148 sort(v.begin(),v.end()); 149 tab.setMin(); 150 tab.init(n,sum); 151 suf.calcSA(s,n+1,128); 152 suf.calcHeight(s,n); 153 suf.solve(n); 154 return 0; 155 }
时间: 2024-10-29 19:06:48