zoukankan      html  css  js  c++  java
  • SPOJ 694&&SPOJ705: Distinct Substrings

    DISUBSTR - Distinct Substrings

    链接

    题意:

      询问有多少不同的子串。

    思路:

      后缀数组或者SAM

      首先求出后缀数组,然后从对于一个后缀,它有n-sa[i]-1个前缀,其中有height[rnk[i]]个被rnk[i]-1的后缀算了。所以再减去height[rnk[i]]即可。

    代码:

    换了板子。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cmath>
     6 
     7 using namespace std;
     8 
     9 const int N = 1010;
    10 char s[N];
    11 int t1[N],t2[N],sa[N],height[N],rnk[N],c[N];
    12 int n;
    13 
    14 void get_sa(int m) {
    15     int *x = t1,*y = t2,i,p;
    16     for (i=1; i<=m; ++i) c[i] = 0;
    17     for (i=1; i<=n; ++i) x[i]=s[i],c[x[i]]++;
    18     for (i=1; i<=m; ++i) c[i] += c[i-1];
    19     for (i=n; i>=1; --i) sa[c[ x[i] ]--] = i;
    20     for (int k=1; k<=n; k<<=1) {
    21         p = 0;
    22         for (i=n-k+1; i<=n; ++i) y[++p] = i;
    23         for (i=1; i<=n; ++i) if (sa[i]>k) y[++p] = sa[i]-k;
    24         for (i=1; i<=m; ++i) c[i] = 0;
    25         for (i=1; i<=n; ++i) c[ x[y[i]] ]++;
    26         for (i=1; i<=m; ++i) c[i] += c[i-1];
    27         for (i=n; i>=1; --i) sa[c[ x[y[i]] ]--] = y[i];
    28         swap(x,y);
    29         p = 2;
    30         x[sa[1]] = 1;
    31         for (i=2; i<=n; ++i)
    32             x[sa[i]] = y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k] ? p-1 : p++;
    33         if (p > n) break;
    34         m = p; 
    35     }
    36 }
    37 void get_height() {
    38     for (int i=1; i<=n; ++i) rnk[sa[i]] = i;
    39     int k = 0;
    40     height[1] = 0;
    41     for (int i=1; i<=n; ++i) {
    42         if (rnk[i]==1) continue;
    43         if (k) k--;
    44         int j = sa[rnk[i]-1];
    45         while (i+k<=n && j+k<=n && s[i+k]==s[j+k])
    46          k++;
    47         height[rnk[i]] = k;
    48     }
    49 }
    50 void get_ans() {
    51     long long ans = 0;
    52     for (int i=1; i<=n; ++i) {
    53         ans += max(n-i+1-height[rnk[i]],0);
    54 //      ans += max(n-sa[i]-height[i],0);
    55     }
    56     cout << ans << '
    ';
    57 }
    58 int main() {
    59     int T;
    60     scanf("%d",&T);
    61     while (T--) {
    62         scanf("%s",s+1);
    63         n = strlen(s+1);
    64         get_sa(130);
    65         get_height();
    66         get_ans();
    67     }
    68     return 0;
    69 }
    View Code

    原来的

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<cmath>
     6 
     7 using namespace std;
     8 
     9 const int N = 1010;
    10 char s[N];
    11 int t1[N],t2[N],sa[N],height[N],rnk[N],c[N];
    12 int n;
    13 
    14 void get_sa(int m) {
    15     int *x = t1,*y = t2;
    16     for (int i=0; i<m; ++i) c[i] = 0;
    17     for (int i=0; i<n; ++i) c[x[i] = s[i]]++;
    18     for (int i=1; i<m; ++i) c[i] += c[i-1];
    19     for (int i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
    20     for (int k=1; k<=n; k<<=1) {
    21         int p = 0;
    22         for (int i=n-k; i<n; ++i) y[p++] = i;
    23         for (int i=0; i<n; ++i) if (sa[i] >= k) y[p++] = sa[i] - k;
    24         for (int i=0; i<m; ++i) c[i] = 0;
    25         for (int i=0; i<n; ++i) c[x[y[i]]]++;
    26         for (int i=1; i<m; ++i) c[i] += c[i-1];
    27         for (int i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
    28         swap(x,y);
    29         p = 1;
    30         x[sa[0]] = 0;
    31         for (int i=1; i<n; ++i)
    32             x[sa[i]] = (y[sa[i-1]]==y[sa[i]] && sa[i-1]+k<n && sa[i]+k<n && 
    33             y[sa[i-1]+k]==y[sa[i]+k]) ? p-1 : p++;
    34             
    35         if (p >= n) break;
    36         m = p;
    37     }
    38 }
    39 void get_height() {
    40     for (int i=0; i<n; ++i) rnk[sa[i]] = i;
    41     int k = 0;
    42     height[0] = 0;
    43     for (int i=0; i<n; ++i) {
    44         if (!rnk[i]) continue;
    45         if (k) k--;
    46         int j = sa[rnk[i]-1];
    47         while (i+k < n && j+k < n && s[i+k]==s[j+k]) k++;
    48         height[rnk[i]] = k;
    49     }
    50 }
    51 void get_ans() {
    52     long long ans = 0;
    53     for (int i=0; i<n; ++i) {
    54         ans += max(n-i-height[rnk[i]],0);
    55 //        ans += max(n-sa[i]-height[i],0);
    56     }
    57     cout << ans << '
    ';
    58 }
    59 int main() {
    60     int T;
    61     scanf("%d",&T);
    62     while (T--) {
    63         scanf("%s",s);
    64         n = strlen(s);
    65         get_sa(130);
    66         get_height();
    67         get_ans();
    68     }
    69     return 0;
    70 }
    View Code
  • 相关阅读:
    策略模式
    简单工厂模式
    单例模式
    sp_xml_preparedocument _使用 处理XML文档
    LINQ to XML
    动态Linq(结合反射)
    IEqualityComparer<T>接口
    Linq to object 技巧、用法集锦
    IComparer<T> 接口Linq比较接口
    Linq to BBJECT之非延时标准查询操作符
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9060912.html
Copyright © 2011-2022 走看看