SPOJ 694 Distinct Substrings(不相同子串个数)

https://vjudge.net/problem/SPOJ-DISUBSTR

题意:

给定一个字符串,求不相同的子串的个数。

 

思路:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<vector>
 6 #include<stack>
 7 #include<queue>
 8 #include<cmath>
 9 #include<map>
10 #include<set>
11 using namespace std;
12 typedef long long ll;
13 typedef pair<int,int> pll;
14 const int INF = 0x3f3f3f3f;
15 const int maxn=1000+5;
16 
17 int n;
18 char s[maxn];
19 int sa[maxn],t[maxn],t2[maxn],c[maxn];
20 int Rank[maxn],height[maxn];
21 
22 void build_sa(int m)
23 {
24     int *x=t,*y=t2;
25     //基数排序
26     for(int i=0;i<m;i++)    c[i]=0;
27     for(int i=0;i<n;i++)    c[x[i]=s[i]]++;
28     for(int i=1;i<m;i++)    c[i]+=c[i-1];
29     for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
30     for(int k=1;k<=n;k<<=1)
31     {
32         int p=0;
33         //直接利用sa数组排序第二关键字
34         for(int i=n-k;i<n;i++)  y[p++]=i;
35         for(int i=0;i<n;i++)    if(sa[i]>=k)    y[p++]=sa[i]-k;
36         //基数排序第一关键字
37         for(int i=0;i<m;i++)    c[i]=0;
38         for(int i=0;i<n;i++)    c[x[y[i]]]++;
39         for(int i=1;i<m;i++)    c[i]+=c[i-1];
40         for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
41         //根据sa和y计算新的x数组
42         swap(x,y);
43         p=1;
44         x[sa[0]]=0;
45         for(int i=1;i<n;i++)
46             x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
47         if(p>=n)
48             break;
49         m=p;                //下次基数排序的最大值
50     }
51 }
52 
53 void getHeight(int n)
54 {
55     int i,j,k=0;
56     for(i=1;i<=n;i++)  Rank[sa[i]]=i;
57     for(i=0;i<n;i++)
58     {
59         if(k)  k--;
60         int j=sa[Rank[i]-1];
61         while(s[i+k]==s[j+k])  k++;
62         height[Rank[i]]=k;
63     }
64 }
65 
66 int main()
67 {
68     //freopen("in.txt","r",stdin);
69     int T;
70     scanf("%d",&T);
71     while(T--)
72     {
73         scanf("%s",s);
74         n=strlen(s);
75         s[n]='0';
76         n++;
77         build_sa(128);
78         getHeight(n-1);
79         int ans=(n-1)*n/2;
80         for(int i=1;i<n;i++)
81             ans-=height[i];
82         printf("%d\n",ans);
83     }
84     return 0;
85 }

 

转载于:https://www.cnblogs.com/zyb993963526/p/7574902.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值