zoukankan      html  css  js  c++  java
  • CF IndiaHacks 2016 F Paper task 后缀数组

    题目链接:http://codeforces.com/problemset/problem/653/F

    大意是给出一个只包含'('和')'的括号串,求有多少不同的子串是合法的括号串

    解法:对于每一个后缀,需要能够求出这个后缀有多少前缀是合法的括号串,这个可以用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
    ",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 }
    View Code
  • 相关阅读:
    一般图最大匹配
    hdu4486 Pen Counts
    hdu4416 Good Article Good sentence (后缀数组)
    hdu2275 Kiki & Little Kiki 1 (多重集合的应用)
    (转)2sat 专题
    DP专题
    开始
    WP7 如何禁用WebBrowser 控件缩放和左右移动
    WP7 Bing Map 显示中文地图
    希望与大家分享新的技术
  • 原文地址:https://www.cnblogs.com/micrari/p/5309075.html
Copyright © 2011-2022 走看看