zoukankan      html  css  js  c++  java
  • SPOJ694 -- DISUBSTR 后缀树组求不相同的子串的个数

    DISUBSTR - Distinct Substrings

     

    Given a string, we need to find the total number of its distinct substrings.

    Input

    T- number of test cases. T<=20;
    Each test case consists of one string, whose length is <= 1000

    Output

    For each test case output one number saying the number of distinct substrings.

    Example

    Sample Input:
    2
    CCCCC
    ABABA

    Sample Output:
    5
    9

    Explanation for the testcase with string ABABA: 
    len=1 : A,B
    len=2 : AB,BA
    len=3 : ABA,BAB
    len=4 : ABAB,BABA
    len=5 : ABABA
    Thus, total number of distinct substrings is 9.

    题意:求不同的子串的个数。

    首先要知道,任意子串必是某一后缀的前缀。对于suffix[sa[i]],  它有len-sa[i]个前缀,,其中lcp[i]个子串与suffix[sa[i-1]]的前缀重复。。

    每次只需要加上 len-sa[i]-lcp[i]就行了。。  

     1 #include <set>
     2 #include <map>
     3 #include <cmath>
     4 #include <ctime>
     5 #include <queue>
     6 #include <stack>
     7 #include <cstdio>
     8 #include <string>
     9 #include <vector>
    10 #include <cstdlib>
    11 #include <cstring>
    12 #include <iostream>
    13 #include <algorithm>
    14 using namespace std;
    15 typedef unsigned long long ull;
    16 typedef long long ll;
    17 const int inf = 0x3f3f3f3f;
    18 const double eps = 1e-8;
    19 const int maxn = 2e4+10;
    20 int sa[maxn], k, len, tmp[maxn], rank[maxn];
    21 string s;
    22 bool cmp(int i, int j)
    23 {
    24     if (rank[i] != rank[j])
    25         return rank[i] < rank[j];
    26     else
    27     {
    28         int x = (i+k <= len ? rank[i+k] : -1);
    29         int y = (j+k <= len ? rank[j+k] : -1);
    30         return x < y;
    31     }
    32 }
    33 void build_sa()
    34 {
    35     for (int i = 0; i <= len; i++)
    36     {
    37         sa[i] = i;
    38         rank[i] = (i < len ? s[i] : -1);
    39     }
    40     for (k = 1; k <= len; k *= 2)
    41     {
    42         sort (sa,sa+len+1,cmp);
    43         tmp[sa[0]] = 0;
    44         for (int i = 1; i <= len; i++)
    45         {
    46             tmp[sa[i]] = tmp[sa[i-1]] + (cmp(sa[i-1],sa[i])? 1 : 0);
    47         }
    48         for (int i = 0; i <= len; i++)
    49             rank[i] = tmp[i];
    50     }
    51 }
    52 int lcp[maxn];
    53 void get_lcp()
    54 {
    55     for (int i = 0; i < len; i++)
    56         rank[sa[i]] = i;
    57     int h = 0;
    58     lcp[0] = 0;
    59     for (int i = 0; i < len; i++)
    60     {
    61         int j = sa[rank[i]-1];
    62         if (h > 0)
    63             h--;
    64         for (; h+i < len && h+j < len; h++)
    65             if (s[i+h] != s[j+h])
    66                 break;
    67         lcp[rank[i]] = h;
    68     }
    69 }
    70 int main()
    71 {
    72     #ifndef ONLINE_JUDGE
    73         freopen("in.txt","r",stdin);
    74     #endif
    75     int T;
    76     scanf ("%d", &T);
    77     while (T--)
    78     {
    79         cin >> s;
    80         len = s.size();
    81         build_sa();
    82         get_lcp();
    83         int ans = 0;
    84         for (int i = 0; i <= len; i++)
    85         {
    86             ans += len - sa[i] - lcp[i];
    87         }
    88         printf ("%d
    ",ans);
    89     }
    90     return 0;
    91 }
  • 相关阅读:
    Blazor使用Chrome远程调试
    Blazor登录Ids4
    Jenkins + Coding 构建 Docker Image 并自动上传至Docker Registry
    EFK 数据生命周期
    EFK (Elasticsearch + Fluentd + Kibana) 日志分析系统
    通过Nginx代理Grafana,并通过域名访问
    Prometheus搜集mysql和nginx log指标
    java 线程相关(4)
    java 并发相关(5)
    java 线程相关(3)
  • 原文地址:https://www.cnblogs.com/oneshot/p/4347510.html
Copyright © 2011-2022 走看看