题意

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

思路

一个字符串的子串都必然是它的某个后缀的前缀。对于每一个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]

转载于:https://www.cnblogs.com/AbandonZHANG/p/4114121.html

SPOJ 694 SPOJ 705 (不重复子串个数:后缀数组)相关推荐

  1. BZOJ3230 相似子串 【后缀数组】

    题目链接 BZOJ3230 权限题 题解 后缀数组基础题 询问第K大不同子串和正反lcp长度 如果您RE了,您就要知道询问的输入会爆LL #include<algorithm> #incl ...

  2. 求两个字符串的LCS(最长公共子串)后缀数组

    题意: 给两个字符串,求出它们的最长公共子串的长度. 比如 yeshowmuchiloveyoumydearmotherreallyicannotbelieveit yeaphowmuchilovey ...

  3. |spoj 694|后缀数组|Distinct Substrings

    spoj 694 给出一个字符串,求字符串中不相同的子串个数. 我们可以知道,字符串中的每个子串都是某个后缀的前缀,于是题目转化为求不相同的后缀的前缀问题.对于每一个SA[k]SA[k]开始的后缀,将 ...

  4. 字符串:字符串顺序比较、11-2删除重复元素、字符串生成器、着急的WYF(不同子串个数)

    字符串顺序比较 问题描述比较两个字符串s1和s2,输出:0表示s1与s2相等:1表示s1的字母序先于s2:-1表示s1的字母序后于s2输入格式输入两行,第一行输入一个字符串1,第二行输入字符串2.输出 ...

  5. SPOJ - PHRASES Relevant Phrases of Annihilation —— 后缀数组 出现于所有字符串中两次且不重叠的最长公共子串...

    题目链接:https://vjudge.net/problem/SPOJ-PHRASES PHRASES - Relevant Phrases of Annihilation no tags  You ...

  6. SPOJ 1811. POJ 2774 . 最大公共子串

    Description 给出两个字符串 a,b ,求 a 和 b 的最大公共子串,字符串长度为 500000. Solution 可以用后缀数组做,将两个字符串接起来,中间用特殊的分隔符相连. 求出 ...

  7. P2408 不同子串个数

    P2408 不同子串个数 题意: 给你一个长为 n 的字符串,求不同的子串的个数. 我们定义两个子串不同,当且仅当有这两个子串长度不一样或者长度一样且有任意一位不一样. 子串的定义:原字符串中连续的一 ...

  8. [SDOI2016] 生成魔咒(后缀数组SA + st表 + set)动态不同子串个数

    problem luogu-P4070 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1,21,21,2 拼凑起来形成一个魔咒串 [1,2][1,2][1,2]. 一个魔咒串 ...

  9. SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)

    [题目链接] http://www.spoj.pl/problems/PHRASES/ [题目大意] 求在每个字符串中出现至少两次的最长的子串 [题解] 注意到这么几个关键点:最长,至少两次,每个字符 ...

最新文章

  1. 【HTML】兴唐二十八节课之常用标签(不定期更新)
  2. 提取稳定前景的两种方法
  3. iptables 防火墙
  4. 一些DIV+CSS 命名规范
  5. Java+大数据开发——Hadoop集群环境搭建(二)
  6. 26个提升java性能需要注意的地方
  7. golang reflect
  8. 2021母婴行业洞察报告
  9. python寻路_【Python】 Numpy极简寻路
  10. JVM虚拟机详解(一)JVM与JAVA体系统结构
  11. 如何利用用户ID号、关键词或视频时长在自媒体视频软件上批量采集下载关于在自媒体视频软件上批量采集...
  12. mysql sql 0填充_sql - MySQL - 如何用“0”填充前面的邮政编码?
  13. 你真的搞懂Class,class了么?
  14. 大三老狗的前端实习半年心得-经验分享
  15. rxj热血江hsf湖私服_如何使用RxJ进行React性思考和动画化移动对象
  16. 华为手机照片如何出现时间地点天气,教你30秒,一学就会
  17. #Reading Paper#Improving Graph Collaborative Filtering with Neighborhood-enriched Contrastive Learni
  18. 001-mac使用桌面、Dock、键盘、程序安装
  19. adobe illustrator如何裁剪图像
  20. 当攀藤 PM2.5 传感器遇上 RT-Thread

热门文章

  1. hosts文件 端口_中望软件:中望3D网络版服务端如何固定端口
  2. Android Location API跟踪您当前的位置
  3. Python字符串串联
  4. 如何卸载FileZilla的Ftp服务
  5. Java面试题:String 和 StringBuffer、StringBuilder 的区别是什么?
  6. SEO哪些因素会照成百度排名不稳定
  7. File Manipulation
  8. Linux I2C设备驱动编写(二)
  9. COCOS2D-X编译成android的项目
  10. 【转】Asp.Net TreeView with CheckBox