spoj694,spoj705 后缀数组/不相同的子串的个数 计算贡献
来源:互联网 发布:mac 游戏加速器 编辑:程序博客网 时间:2024/06/08 00:06
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[1]), suffix(sa[2]),
suffix(sa[3]), ...... ,suffix(sa[n])的顺序计算,不难发现,对于每一次新加
进来的 后缀 suffix(sa[k]), 它将产生 n-sa[k]+1 个新 的前缀。 但是其中有
height[k]个是和前面的字符串的前缀是相同的。所以 suffix(sa[k])将“贡献”
出 n-sa[k]+1- height[k]个不同的子串。累加后便是原问题的答案。这个做法
的时间复杂度为 O(n)。
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 100005;struct SuffixArray { char s[maxn]; // 原始字符数组(最后一个字符应必须是0,而前面的字符必须非0) int sa[maxn]; // 后缀数组 int rank1[maxn]; // 名次数组. rank[0]一定是n-1,即最后一个字符 int height[maxn]; // height数组 int t[maxn], t2[maxn], c[maxn]; // 辅助数组 int n; // 字符个数 void clear() { n = 0; memset(sa, 0, sizeof(sa)); } // m为最大字符值加1。调用之前需设置好s和n void build_sa(int m) { int i, *x = t, *y = t2; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[i] = s[i]]++; for(i = 1; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; for(int k = 1; k <= n; k <<= 1) { int p = 0; for(i = n-k; i < n; i++) y[p++] = i; for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[y[i]]]++; for(i = 0; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(i = 1; i < n; i++) x[sa[i]] = y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k] ? p-1 : p++; if(p >= n) break; m = p; } } void build_height() { int i, j, k = 0; for(i = 0; i < n; i++) rank1[sa[i]] = i; for(i = 0; i < n; i++) { if(k) k--; int j = sa[rank1[i]-1]; while(s[i+k] == s[j+k]) k++; height[rank1[i]] = k; } }};SuffixArray sol;int T;int main(){// freopen("data.txt","r",stdin); ios_base::sync_with_stdio(false); cin >> T; while(T--) { memset(sol.s,0,sizeof(sol.s)); cin >> sol.s; sol.clear(); sol.n = strlen(sol.s)+1; sol.build_sa(130);// for(int i=0;i<sol.n;i++)// {// cout << sol.sa[i]<<" ";// }// cout <<endl; sol.build_height();// sol.n--; ll ans = 0 ; for(int i=1;i<sol.n;i++) { ans += sol.n - sol.sa[i]-1 - sol.height[i]; } cout << ans<<endl; } return 0;}
- spoj694,spoj705 后缀数组/不相同的子串的个数 计算贡献
- 【后缀数组求不相同的子串的个数】spoj694 spoj705
- 后缀数组(不相同子串的个数)spoj694
- SPOJ694 Distinct Substrings, 后缀数组, 不相同的子串的个数
- spoj694 不相同的子串的个数(后缀数组)
- Spoj694(Distinct Substrings)求字符串不相同的子串个数(后缀数组)
- spoj705( 求不相同的子串个数)
- [spoj694]不相同的子串的个数
- SPOJ694&SPOJ705(后缀数组)
- SPOJ694 && SPOJ705 ——不同子串的总数
- spoj694 Distinct Substrings(后缀数组+统计不同子串的个数)
- SPOJ694&&SPOJ705:Distinct Substrings(后缀数组)
- SPOJ694&&SPOJ705:Distinct Substrings (后缀数组)
- SPOJ 694. Distinct Substrings (不相同的子串的个数--后缀数组)
- HDU 5769-Substring(后缀数组-不相同的子串的个数)
- SPOJ 694 / SPOJ DISUBSTR Distinct Substrings【后缀数组】不相同的子串的个数
- SPOJ DISUBSTR - Distinct Substrings(后缀数组[不相同的子串的个数])
- SPOJ SUBST1 - New Distinct Substrings(后缀数组[不相同的子串的个数])
- 探讨scanf函数
- RabbitMQ关于吞吐量,延迟和带宽的一些理论
- 路由器上串口、以太网口、控制口和VTY口的区别
- vue 移动端今天写了一个根据后台传过来的http状态码,来实现跳转error页面
- c指针终
- spoj694,spoj705 后缀数组/不相同的子串的个数 计算贡献
- jQuery 效果方法
- 如何使用Nginx搭建WCF集群!
- ORACLE 关闭sql tuner
- 深入了解scanf() getchar()和gets()等函数之间的区别
- Spark在Hadoop的HDFS中读取数据
- Oracle10g的安装
- 转载:phxpaxos源码阅读系列
- android问题和小技巧记录