• Distinct Substrings SPOJ


    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])可以产生n-sa[i]+1个前缀
    但是有重复的,重复个数就是height[i]
    所有不重复前缀是n-sa[i]+1-height[i]
    注意第0号后缀是没法和第-1号后缀比较(因为第-1号后缀就不存在)
    这样的话就会导致最后的答案少计算
    这里采用的方法就是给这个字符串后面加一个未出现过的字符
    这个新长度的字符串求解
     
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
     5 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
     6 using namespace std;
     7 const int N = 1005;
     8 int c[N],sa[N*3];
     9 int ranks[N*3], height[N*3],s[N];
    10 char str[N];
    11 bool pan(int *x,int i,int j,int k,int n)
    12 {
    13     int ti=i+k<n?x[i+k]:-1;
    14     int tj=j+k<n?x[j+k]:-1;
    15     return x[i]==x[j]&&ti==tj;
    16 }
    17 void build_SA(int n,int r)
    18 {
    19     int *x=ranks,*y=height;
    20     for(int i=0; i<r; i++)c[i]=0;
    21     for(int i=0; i<n; i++)c[s[i]]++;
    22     for(int i=1; i<r; i++)c[i]+=c[i-1];
    23     for(int i=n-1; i>=0; i--)sa[--c[s[i]]]=i;
    24     r=1;
    25     x[sa[0]]=0;
    26     for(int i=1; i<n; i++)
    27         x[sa[i]]=s[sa[i]]==s[sa[i-1]]?r-1:r++;
    28     for(int k=1; r<n; k<<=1)
    29     {
    30         int yn=0;
    31         for(int i=n-k; i<n; i++)y[yn++]=i;
    32         for(int i=0; i<n; i++)
    33             if(sa[i]>=k)y[yn++]=sa[i]-k;
    34         for(int i=0; i<r; i++)c[i]=0;
    35         for(int i=0; i<n; i++)++c[x[y[i]]];
    36         for(int i=1; i<r; i++)c[i]+=c[i-1];
    37         for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
    38         swap(x,y);
    39         r=1;
    40         x[sa[0]]=0;
    41         for(int i=1; i<n; i++)
    42             x[sa[i]]=pan(y,sa[i],sa[i-1],k,n)?r-1:r++;
    43     }
    44     for(int i=0; i<n; i++)ranks[i]=x[i];
    45 }
    46 void get_height(int n)
    47 {
    48     int i,j,k=0;
    49     for(i=1; i<=n; i++)ranks[sa[i]]=i;
    50     for(i=0; i<n; i++)
    51     {
    52         if(k)k--;
    53         else k=0;
    54         j=sa[ranks[i]-1];
    55         while(s[i+k]==s[j+k])k++;
    56         height[ranks[i]]=k;
    57     }
    58 }
    59 int main() {
    60     int t;
    61     scanf("%d", &t);
    62     while (t--) {
    63         scanf("%s", str);
    64         int len = strlen(str);
    65         for (int i = 0; i < len; i++)
    66             s[i] = (int)str[i];
    67         s[len] = 0;
    68         build_SA(len+1,200);
    69         get_height(len);
    70         int res = 0;
    71         for (int i = 1; i <= len; i++)
    72             //printf("%d ",height[i]),
    73             res += ((len-1) - sa[i]+1 - height[i]);
    74         printf("%d
    ", res);
    75     }
    76     return 0;
    77 }
     
    解法二、
    先请出来一共有多少子串,即(n+1)*n/2个,然后height数组的值就是相同前缀的数量,所以用总个数减去这个字符串的所有后缀
    形成的height就是结果
    因为我的代码在原字符串基础上添加了一个字符,所以第0号后缀不是原字符串的,所以for循环从2到n
     
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
     5 #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
     6 using namespace std;
     7 const int N = 1005;
     8 int c[N],sa[N*3];
     9 int ranks[N*3], height[N*3],s[N];
    10 char str[N];
    11 bool pan(int *x,int i,int j,int k,int n)
    12 {
    13     int ti=i+k<n?x[i+k]:-1;
    14     int tj=j+k<n?x[j+k]:-1;
    15     return x[i]==x[j]&&ti==tj;
    16 }
    17 void build_SA(int n,int r)
    18 {
    19     int *x=ranks,*y=height;
    20     for(int i=0; i<r; i++)c[i]=0;
    21     for(int i=0; i<n; i++)c[s[i]]++;
    22     for(int i=1; i<r; i++)c[i]+=c[i-1];
    23     for(int i=n-1; i>=0; i--)sa[--c[s[i]]]=i;
    24     r=1;
    25     x[sa[0]]=0;
    26     for(int i=1; i<n; i++)
    27         x[sa[i]]=s[sa[i]]==s[sa[i-1]]?r-1:r++;
    28     for(int k=1; r<n; k<<=1)
    29     {
    30         int yn=0;
    31         for(int i=n-k; i<n; i++)y[yn++]=i;
    32         for(int i=0; i<n; i++)
    33             if(sa[i]>=k)y[yn++]=sa[i]-k;
    34         for(int i=0; i<r; i++)c[i]=0;
    35         for(int i=0; i<n; i++)++c[x[y[i]]];
    36         for(int i=1; i<r; i++)c[i]+=c[i-1];
    37         for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i];
    38         swap(x,y);
    39         r=1;
    40         x[sa[0]]=0;
    41         for(int i=1; i<n; i++)
    42             x[sa[i]]=pan(y,sa[i],sa[i-1],k,n)?r-1:r++;
    43     }
    44     for(int i=0; i<n; i++)ranks[i]=x[i];
    45 }
    46 void get_height(int n)
    47 {
    48     int i,j,k=0;
    49     for(i=1; i<=n; i++)ranks[sa[i]]=i;
    50     for(i=0; i<n; i++)
    51     {
    52         if(k)k--;
    53         else k=0;
    54         j=sa[ranks[i]-1];
    55         while(s[i+k]==s[j+k])k++;
    56         height[ranks[i]]=k;
    57     }
    58 }
    59 int main()
    60 {
    61     int t;
    62     scanf("%d", &t);
    63     while (t--)
    64     {
    65         scanf("%s", str);
    66         int len = strlen(str);
    67         for (int i = 0; i < len; i++)
    68             s[i] = (int)str[i];
    69         s[len] = 0;
    70         build_SA(len+1,200);
    71         get_height(len);
    72         int res = ((len+1)*len)/2;
    73         for (int i = 2; i <= len; i++)
    74             //printf("%d ",height[i]),
    75             res -= height[i];
    76         printf("%d
    ", res);
    77     }
    78     return 0;
    79 }
     
  • 相关阅读:
    促仅开发者间交流与合作的胡思乱想
    Unity3D音乐音效研究-MIDI与波表
    剑英陪你玩转图形学 (二)彩虹
    java mail实现Email的发送,完整代码
    linux 下 安装 rpm 格式 的 mysql
    ExtJs3带条件的分页查询的实现
    查看linux的版本信息
    java 非法字符过滤 , 半角/全角替换
    MySQL数据库错误server_errno=2013的解决
    MySQL数据库双机热备份
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/12322405.html
Copyright © 2020-2023  润新知