SPOJ 694 && SPOJ 705 (不重复子串个数:后缀数组)
题意
给定一个字符串,求它的所有不重复子串的个数
思路
一个字符串的子串都必然是它的某个后缀的前缀。对于每一个sa[i]后缀,它的起始位置sa[i],那么它最多能得到该后缀长度个子串(n-sa[i]个),而其中有height[i]个是与前一个后缀相同的,所以它能产生的实际后缀个数便是n-sa[i]-height[i]。遍历一次所有的后缀,将它产生的后缀数加起来便是答案。
代码
[cpp]
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
using namespace std;
//Suffix Array
const int maxn = 1005;
int wx[maxn], wy[maxn], wxy[maxn], hs[maxn];
int r[maxn], sa[maxn], ranks[maxn], height[maxn];
int cmp(int r[], int a, int b, int l){
return (r[a] == r[b] && r[a+l] == r[b+l]);
}
//r is the string, and r[n-1] = 0, this means we should add a '0' at the end of the string.
void da(int r[], int sa[], int ranks[], int height[], int n, int m){
//calculate sa[], begin at 1 because sa[0] = "0".
int i, j, len, p, k = 0, *x = wx, *y = wy, *t;
for (i = 0; i < m; i ++) hs[i] = 0;
for (i = 0; i < n; i ++) hs[x[i] = r[i]] ++;
for (i = 1; i < m; i ++) hs[i] += hs[i-1];
for (i = n-1; i >= 0; i --) sa[-- hs[x[i]]] = i;
for (len = 1, p = 1; p < n; len *= 2, m = p){
for (p = 0, i = n - len; i < n; i ++) y[p ++] = i;
for (i = 0; i < n; i ++) if (sa[i] >= len) y[p ++] = sa[i] - len;
for (i = 0; i < n; i ++) wxy[i] = x[y[i]];
for (i = 0; i < m; i ++) hs[i] = 0;
for (i = 0; i < n; i ++) hs[wxy[i]] ++;
for (i = 1; i < m; i ++) hs[i] += hs[i-1];
for (i = n-1; i >= 0; i --) sa[-- hs[wxy[i]]] = y[i];
for (t = x, x = y, y = t, p = 1, i = 1, x[sa[0]] = 0; i < n; i ++)
x[sa[i]] = cmp(y, sa[i-1], sa[i], len)?p-1:p ++;
}
//calculate height[], height[n-1] is null because we add a '0' at the end of the string.
for (i = 1; i < n; i ++) ranks[sa[i]] = i;
for (i = 0; i < n - 1; height[ranks[i++]] = k)
for (k?k--:0, j = sa[ranks[i]-1]; r[i+k] == r[j+k]; k ++);
}
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int t;
scanf("%d", &t);
while(t --){
char tmps[1005] = {0};
scanf("%s", tmps);
MEM(r, 0);
int n = strlen(tmps);
for (int i = 0; i < n; i ++) r[i] = tmps[i];
da(r, sa, ranks, height, n + 1, 100);
int res = 0;
for (int i = 1; i <= n; i ++){
res += n - sa[i] - height[i];
}
printf("%d\n", res);
}
return 0;
}
[/cpp]
SPOJ 694 && SPOJ 705 (不重复子串个数:后缀数组)的更多相关文章
- POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)+后缀数组模板
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 7586 Accepted: 3448 Cas ...
- cogs1709. [SPOJ 705] 不同的子串(后缀数组
http://cogs.pro:8080/cogs/problem/problem.php?pid=vyziQkWaP 题意:给定一个字符串,计算其不同的子串个数. 思路:ans=总共子串个数-相同的 ...
- POJ 3261 可重叠的 k 次最长重复子串【后缀数组】
这也是一道例题 给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠.算法分析:这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组.不同的是,这里要判断的是有没有一个组 ...
- POJ1743 Musical Theme 最长重复子串 利用后缀数组
POJ1743 题目意思是求不重叠的最长相同变化的子串,输出该长度 比如1 2 3 4 5 6 7 8 9 10,最长长度为5,因为子串1 2 3 4 5 和 6 7 8 9 10变化都一样的 思路: ...
- 【poj3693-重复次数最多的连续重复子串】后缀数组
题意:给定一个串,长度<=10^5,求它重复次数最多的连续重复子串(输出字典序最小的那个). 例如ccabcabc,答案就是abcabc 一开始没想清楚,结果调了好久. 原理: 按照L划分,因为 ...
- 洛谷P2408 不同子串个数 后缀数组 + Height数组
## 题目描述: 给你一个长为 $N$ $(N<=10^5)$ 的字符串,求不同的子串的个数我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样.子串的定义:原字 ...
- LUOGU P2408 不同子串个数(后缀数组)
传送门 解题思路 后缀数组求本质不同串的裸题.\(ans=\dfrac{n(n+1)}{2} -\sum height[i]\). 代码 #include<iostream> #inclu ...
- ACdream 1430——SETI——————【后缀数组,不重叠重复子串个数】
SETI Time Limit: 4000/2000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statist ...
- 【SPOJ】Distinct Substrings/New Distinct Substrings(后缀数组)
[SPOJ]Distinct Substrings/New Distinct Substrings(后缀数组) 题面 Vjudge1 Vjudge2 题解 要求的是串的不同的子串个数 两道一模一样的题 ...
随机推荐
- Delphi APP 開發入門(一)重生的 Delphi
Delphi APP 開發入門(一)重生的 Delphi 分享: Share on facebookShare on twitterShare on google_plusone_share 閲讀 ...
- Linux系统——源码编译安装
记得要先去把httpd-2.2.9.tar.gz通过xftp进行文件传输第一步:yum仓库下安装编译环境的支持程序 #yum -y install gcc gcc-c++ make 第二步:将源码包h ...
- javascript面向对象笔记(一)
ECMAscript对象(以下简称对象): ECMA-262把对象定义为:无序属性的集合,其属性可以包含基本值.对象或者函数. 对象的每个属性或方法都有一个名字,而每个名字都映射到一个值.值可以是数据 ...
- maven工具使用之常用maven命令(二)
1.创建java web项目: # mvn archetype:generate -DgroupId=com.igoodful.sdxs -DartifactId=hubu -Darche ...
- vue跳转页面传值怎么传?
这是路由跳转: this.$router.push( { name: 'holderResult', params: { meetingId:self.$route.params.meetingId} ...
- IDEA创建Spring Boot的项目
IDEA创建SpringBoot的项目非常的方便智能,可以实现零配置,只需要在创建的时候勾选你需要的功能,比如mybatis,mysql等等,它会帮你自动下载导入响应的jar,不用自己再去手动填写. ...
- 由浅入深之Tensorflow(2)----logic_regression实现
import tensorflow as tf import numpy as np from tensorflow.examples.tutorials.mnist import input_dat ...
- iOS APP 新增表情包拓展
图示教程如下:
- pyinstaller 打包生成的exe文件,在其他电脑上报错
解决方法: 1.第一种情况,在打包的时候不要加参数-w,看一下执行exe文件后出现的报错再看下一步的行动 2.应该是需要装一个VC 2015 x64(下载地址:https://www.microsof ...
- 对于JVM中方法区,永久代,元空间以及字符串常量池的迁移和string.intern方法
在Java虚拟机(以下简称JVM)中,类包含其对应的元数据,比如类的层级信息,方法数据和方法信息(如字节码,栈和变量大小),运行时常量池,已确定的符号引用和虚方法表. 在过去(当自定义类加载器使用不普 ...