SPOJ 694 DISUBSTR Distinct Substrings 后缀数组
来源:互联网 发布:天谕捏脸萝莉数据 编辑:程序博客网 时间:2024/06/05 19:10
题目大意:
对于给出的字符串(长度不超过1000) 求其不同的子串的个数
大致思路:
就是一个简单的height数组性质的利用,
如果每个子串我们用从位置j开始且长度为k来表示不同的子串的话则一个height[i]值说明表示
从位置sa[i - 1]开始的和sa[i]开始的长度为k <= height[i]的子串相同
所以用全部的子串数减去重复出现的即可, 具体见代码注释
代码如下:
Result : Accepted Memory : 3174 KB Time : 0 ms
/* * Author: Gatevin * Created Time: 2015/2/9 13:25:03 * File Name: Iris_Freyja.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;#define maxn 1233/* * Doubling Algorithm 求后缀数组 */int wa[maxn], wb[maxn], wv[maxn], Ws[maxn];int cmp(int *r, int a, int b, int l){ return r[a] == r[b] && r[a + l] == r[b + l];}void da(int *r, int *sa, int n, int m){ int *x = wa, *y = wb, *t, i, j, p; for(int i = 0; i < m; i++) Ws[i] = 0; for(int i = 0; i < n; i++) Ws[x[i] = r[i]]++; for(int i = 1; i < m; i++) Ws[i] += Ws[i - 1]; for(int i = n - 1; i >= 0; i--) sa[--Ws[x[i]]] = i; for(j = 1, p = 1; p < n; j *= 2, m = p) { for(p = 0, i = n - j; i < n; i++) y[p++] = i; for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j; for(i = 0; i < n; i++) wv[i] = x[y[i]]; for(i = 0; i < m; i++) Ws[i] = 0; for(i = 0; i < n; i++) Ws[wv[i]]++; for(i = 1; i < m; i++) Ws[i] += Ws[i - 1]; for(i = n - 1; i >= 0; i--) sa[--Ws[wv[i]]] = y[i]; for(t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++; } return;}int rank[maxn], height[maxn];void calheight(int *r, int *sa, int n){ int i, j, k = 0; for(i = 1; i <= n; i++) rank[sa[i]] = i; for(i = 0; i < n; height[rank[i++]] = k) for(k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++); return;}char in[maxn];int s[maxn];int sa[maxn];int main(){ int t; scanf("%d", &t); while(t-->0) { scanf("%s", in); int n = strlen(in); for(int i = 0; i < n; i++) s[i] = in[i]; s[n] = 0; da(s, sa, n + 1, 130); calheight(s, sa, n); int ans = n*(n + 1)/2;//所有的子串数C[n][1] + C[n][2] /* * 利用height数组的性质 * 由于每个子串我们用从位置j开始且长度为k来表示不同的子串的话 * 则一个height[i]值表示 * 从位置sa[i - 1]开始的和sa[i]开始的长度为k <= height[i]的子串相同 * 所以将总数减去这个值即可 * 遍历一遍height数组去重就可以得到答案 */ for(int i = 1; i <= n; i++) ans -= height[i]; printf("%d\n", ans); } return 0;}
0 0
- SPOJ 694 DISUBSTR Distinct Substrings 后缀数组
- [SPOJ DISUBSTR]Distinct Substrings(后缀数组)
- SPOJ DISUBSTR Distinct Substrings (后缀数组)
- 【SPOJ-DISUBSTR】Distinct Substrings【后缀数组】
- 【SPOJ DISUBSTR】Distinct Substrings 后缀数组
- SPOJ DISUBSTR Distinct Substrings(后缀数组)
- spoj 694 DISUBSTR - Distinct Substrings (后缀数组)
- SPOJ DISUBSTR Distinct Substrings 后缀数组子串个数
- SPOJ 694 / SPOJ DISUBSTR Distinct Substrings【后缀数组】不相同的子串的个数
- SPOJ DISUBSTR Distinct Substrings
- SPOJ DISUBSTR Distinct Substrings
- SPOJ - DISUBSTR Distinct Substrings
- SPOJ DISUBSTR Distinct Substrings
- SPOJ694--- DISUBSTR - Distinct Substrings(后缀数组)
- [SPOJ705]DISUBSTR - Distinct Substrings(后缀数组)
- SPOJ 694 Distinct Substrings(后缀数组)
- 【后缀数组】【spoj 694】Distinct Substrings
- spoj 694 Distinct Substrings (后缀数组应用)
- Objective-c Run Time
- LeetCode Generate Parentheses
- Android中的Selector的用法
- javax.servlet.http.Cookie API翻译
- nodejs+express+ajax实现图片上传及显示
- SPOJ 694 DISUBSTR Distinct Substrings 后缀数组
- Mac下启动Android SDK Manager更新Android SDK
- 智能家居pocket house构想
- TCP/IP 详解卷一 - TCP的定时器和拥塞控制
- cloudstack4.4.2源码编译成tar包
- Tomcat安装问题
- LeetCode——Repeated DNA Sequences
- 从今天开始写技术博客
- 黑马程序员- IOS学习笔记-Foundation框架