题意

给定一个字符串,求它的所有不重复子串的个数

思路

一个字符串的子串都必然是它的某个后缀的前缀。对于每一个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 (不重复子串个数:后缀数组)的更多相关文章

  1. POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)+后缀数组模板

    Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7586   Accepted: 3448 Cas ...

  2. cogs1709. [SPOJ 705] 不同的子串(后缀数组

    http://cogs.pro:8080/cogs/problem/problem.php?pid=vyziQkWaP 题意:给定一个字符串,计算其不同的子串个数. 思路:ans=总共子串个数-相同的 ...

  3. POJ 3261 可重叠的 k 次最长重复子串【后缀数组】

    这也是一道例题 给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠.算法分析:这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组.不同的是,这里要判断的是有没有一个组 ...

  4. 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变化都一样的 思路: ...

  5. 【poj3693-重复次数最多的连续重复子串】后缀数组

    题意:给定一个串,长度<=10^5,求它重复次数最多的连续重复子串(输出字典序最小的那个). 例如ccabcabc,答案就是abcabc 一开始没想清楚,结果调了好久. 原理: 按照L划分,因为 ...

  6. 洛谷P2408 不同子串个数 后缀数组 + Height数组

    ## 题目描述: 给你一个长为 $N$ $(N<=10^5)$ 的字符串,求不同的子串的个数我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样.子串的定义:原字 ...

  7. LUOGU P2408 不同子串个数(后缀数组)

    传送门 解题思路 后缀数组求本质不同串的裸题.\(ans=\dfrac{n(n+1)}{2} -\sum height[i]\). 代码 #include<iostream> #inclu ...

  8. ACdream 1430——SETI——————【后缀数组,不重叠重复子串个数】

    SETI Time Limit: 4000/2000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit Statist ...

  9. 【SPOJ】Distinct Substrings/New Distinct Substrings(后缀数组)

    [SPOJ]Distinct Substrings/New Distinct Substrings(后缀数组) 题面 Vjudge1 Vjudge2 题解 要求的是串的不同的子串个数 两道一模一样的题 ...

随机推荐

  1. python 中字典的操作(增、删、改、查)

    字典是另一种可变容器模型,且可存储任意类型对象,下标从0开始,最后一个为-1. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({}) ...

  2. appium ios 自动化测试

    iOS自动化测试:Appium 从入门到实践https://www.jianshu.com/p/43f858180557appium自动化测试iOS Demohttps://www.jianshu.c ...

  3. 一步一步学EF系列三【数据迁移】

    我们每篇的内容都不多,所以希望在学习的过程中最后能亲自敲一下代码 这样更有利于掌握. 我们现在接着上篇的例子,我们现在给随便的表增加一个字段 CreateTime 创建日期 运行一下 看看会怎么样 修 ...

  4. Postman 把response的值自动放到变量里

    @ 1里面定义个变量2 3这里加上postman.setEnvironmentVariable("MatchID",JSON.parse(responseBody)); 这样rep ...

  5. selenium+python—实现自动化测试基本思路

    测试是一个贯穿于整个开发过程的连续过程,测试最基本的原理就是比较预期结果是否与实际执行结果相同,如果相同则测试成功,否则测试失败. 为了让单元测试代码能够被测试和维护人员更容易地理解,最好的解决办法是 ...

  6. [原创] css中的绝对定位和相对定位

    我对博客的认识是:记录问题,解决问题,分享知识.如果有轮子,我不需要造轮子.   首先,定位无论是相对定位还是绝对定位,必须有一个参考项,而这个参考项,专业术语称之为 包含块,这里的包含块是指在定位时 ...

  7. Docker-docker制作镜像

    一.下载镜像 a.以daocloud为mirror下载Nginx镜像 配置daocloud为mirror,下载Nginx镜像:(daocloud官网登陆后,发现镜像里找到Nginx镜像) 下载Ngin ...

  8. Web安全学习笔记之Kali部署DVWA和OWASPBWA

    0x0 前言 kali安装完成,下面要进行实战操作了,喵~~(OWASPBWA请直接跳到第八部分) #既然你诚心诚意的问了,我们就大发慈悲的告诉你! #为了防止世界被破坏! #为了守护世界的和平! # ...

  9. windows使用IPC和文件共享

    远程访问windows资源有很多方式,如果给自己用可以使用ipc或开启共享设置只共享给特定用户.如果给所有人用,可以开启everyone共享和guest账户 { "远程获取Windows资源 ...

  10. TensorFlow和深度学习入门教程(TensorFlow and deep learning without a PhD)【转】

    本文转载自:https://blog.csdn.net/xummgg/article/details/69214366 前言 上月导师在组会上交我们用tensorflow写深度学习和卷积神经网络,并把 ...