F - New Distinct Substrings (后缀数组)
题目链接:https://cn.vjudge.net/contest/283743#problem/F
题目大意:给你一个字符串,然后让你求出不同的子串的个数。
具体思路:首先,一个字符串中总的子串个数是len*(len+1)/2,然后就开始去重了,通过height数组,求出所有重复的子串的个数,然后就用总的子串的个数-重复的子串的个数就可以了。
AC代码:
1 #include<iostream> 2 #include<stack> 3 #include<cstring> 4 #include<iomanip> 5 #include<stdio.h> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 # define ll long long 10 const int maxn = 5e5+100; 11 int cntA[maxn], cntB[maxn], sa[maxn], tsa[maxn], A[maxn], B[maxn], height[maxn]; 12 int Rank[maxn]; 13 char ch[maxn]; 14 ll n; 15 //sa[i]代表第i小的后缀位置,Rank[i]代表第i位置开始的后缀在所有的后缀串中排名第几 16 // height[i]代表排名第i个字符串和第i-1个字符串的相同前缀的长度 17 void cal() 18 { 19 for(int i = 0; i < 256; i++) cntA[i] = 0; 20 for(int i = 1; i <= n; i++) cntA[ch[i-1]]++; 21 for(int i = 1; i < 256; i++) cntA[i] += cntA[i-1]; 22 for(int i = n; i; i--) sa[cntA[ch[i-1]]--] = i; 23 Rank[sa[1]] = 1; 24 for(int i = 2; i <= n; i++) 25 { 26 Rank[sa[i]] = Rank[sa[i-1]]; 27 if(ch[sa[i]-1] != ch[sa[i-1]-1]) Rank[sa[i]]++; 28 } 29 for(int l = 1; Rank[sa[n]] < n; l <<= 1) 30 { 31 memset(cntA, 0, sizeof(cntA)); 32 memset(cntB, 0, sizeof(cntB)); 33 for(int i = 1; i <= n; i++) 34 { 35 cntA[A[i] = Rank[i]]++; 36 cntB[B[i] = (i+l <= n)?Rank[i+l]:0]++; 37 } 38 for(int i = 1; i <= n; i++) cntB[i] += cntB[i-1]; 39 for(int i = n; i; i--) tsa[cntB[B[i]]--] = i; 40 for(int i = 1; i <= n; i++) cntA[i] += cntA[i-1]; 41 for(int i = n; i; i--) sa[cntA[A[tsa[i]]]--] = tsa[i]; 42 Rank[sa[1]]=1; 43 for(int i = 2; i <= n; i++) 44 { 45 Rank[sa[i]] = Rank[sa[i-1]]; 46 if(A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]]) Rank[sa[i]]++; 47 } 48 } 49 for(int i = 1, j = 0; i <= n; i++) 50 { 51 if(j) j--; 52 while(ch[i+j-1] == ch[sa[Rank[i]-1] + j - 1]) j++; 53 height[Rank[i]] = j; 54 } 55 } 56 int main() 57 { 58 int T; 59 scanf("%d",&T); 60 while(T--) 61 { 62 scanf("%s",ch); 63 n=strlen(ch); 64 if(n==1) 65 { 66 printf("1\n"); 67 continue; 68 } 69 // cout<<1<<endl; 70 cal(); 71 ll ans=n*(n+1)/2; 72 //cout<<ans<<endl; 73 for(int i=2; i<=n; i++) 74 { 75 ans-=height[i]; 76 // cout<<i<<" "<<height[i]<<endl; 77 } 78 printf("%lld\n",ans); 79 } 80 return 0; 81 }