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 题解 要求的是串的不同的子串个数 两道一模一样的题 ...
随机推荐
- python16_day23【cmdb前端】
一.cmdb前端 https://github.com/willianflasky/growup/tree/master/s16/homework/day23_cmdb_web/s16MadKing ...
- WKWebkit使用
webkit使用WKWebView来代替IOS的UIWebView和OSX的WebView,并且使用Nitro JavaScript引擎,这意味着所有第三方浏览器运行JavaScript将会跟safa ...
- JAVA中hashmap的分析
从http://blog.csdn.net/luanlouis/article/details/41576373?utm_source=tuicool&utm_medium=referral学 ...
- Java枚举类型定义方式
public enum Method { // get请求 GET("get"), // post请求 POST("post"); private String ...
- jsp 小记
1. select 默认选中: <select name="skills" multiple="true"> <option value=&q ...
- [2011-3-9 12:59 ]As3.0中的位图(Bitmap/BitmapData)用法
1.位图使用(模糊)滤镜 //创建一个矩形区域的BitmapData var bmd:BitmapData = new BitmapData(80, 30, false, 0xefefef); //画 ...
- vue下载文件
import fileDownload from 'js-file-download' let params = { ", ", "filename":&quo ...
- CSS Box Model(盒子模型)
CSS Box Model(盒子模型) 一.简介 所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用. CSS盒模型本质上是一个盒子,封 ...
- SpringCloud Feign报错:Method has too many Body parameters
1.feign多参数问题 1.1GET方式 错误写法 @RequestMapping(value="/test", method=RequestMethod.GET) Model ...
- mybatis缓存有关的设置和属性
知识点:mybatis缓存相关的设置和属性 重点:每次执行增删改操作后,一二级缓存被清空,是因为标签设置默认属性为 flushCache="true" (1) <!-- 全局 ...