题面

题意:

给一个字符串,求它有多少个不同的子串

多组数据。

Solution :

模板题,用所有的减去重复的即可。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring> using namespace std; const int N = 1e6; char str[N + 1]; namespace SA { int sa[N + 1], rk[N + 1], height[N + 1]; int a[N+1], set[N+1], n;
int fir[N+1], sec[N+1], buc[N+1], tp[N+1]; void sufSort() {
n = strlen(str + 1);
copy(str + 1, str + 1 + n, set + 1);
sort(set + 1, set + n + 1);
int *end = unique(set + 1, set + n + 1);
for (int i = 1; i <= n; ++ i)
a[i] = lower_bound(set + 1, end, str[i]) - set; fill(buc, buc + 1 + n, 0);
for (int i = 1; i <= n; ++ i) buc[a[i]] ++;
for (int i = 1; i <= n; ++ i) buc[i] += buc[i - 1];
for (int i = 1 ;i <= n; ++ i) rk[i] = buc[a[i] - 1] + 1; for (int t = 1; t <= n; t <<= 1) {
copy(rk + 1, rk + 1 + n, fir + 1);//那张图
for (int i = 1; i <= n; ++ i) sec[i] = i + t > n ? 0 : rk[i + t]; fill(buc, buc + 1 + n, 0);//基排桶清空
for (int i = 1; i <= n; ++ i) buc[sec[i]] ++;
for (int i = 1; i <= n; ++ i) buc[i] += buc[i - 1];//统计比sec[i]小的数有多少个
//tp[i]为第二关键字为第i大的二元组在排序前的位置
//n - --buc[sec[i]]为排名(第几大), 排序前的位置自然是i.
for (int i = 1; i <= n; ++ i) tp[n - --buc[sec[i]]] = i; fill(buc, buc + 1 + n, 0);
for (int i = 1; i <= n; ++ i) buc[fir[i]] ++;
for (int i = 1; i <= n; ++ i) buc[i] += buc[i - 1];
//i为第二关键字为j大的二元组的位置,j递增,即保证sec[i]递增, 所以基排就是正确的。
for (int j = 1, i; j <= n; ++ j) i = tp[j], sa[buc[fir[i]]--] = i;
//手模,理解. bool unique = 1;//若关键字相同,则排名也要相同,而基排使rk不同
for (int j = 1, i, last = 0; j <= n; ++ j) {
i = sa[j];
if (!last) rk[i] = 1;
else if (sec[i] == sec[last] && fir[i] == fir[last])
rk[i] = rk[last], unique = 0;
else
rk[i] = rk[last] + 1;
last = i;
}
if (unique) break;//如果所有rk都不同,就证明排好了.
}
} void getHeight() {
for (int i = 1, k = 0; i <= n; ++ i) {
if (rk[i] == 1) k = 0;
else {
if (k > 0) k --;
int j = sa[rk[i] - 1];
while (j + k <= n && i + k <= n && str[i + k] == str[j + k]) k ++;
}
height[rk[i]] = k;
}
}
}using namespace SA; int main() {
int T; scanf("%d", &T);
while (T --) {
scanf("%s", str + 1);
int n = strlen(str + 1);
sufSort();
getHeight();
int ans = n * (n + 1) / 2;
for (int i = 2; i <= n; ++ i) ans -= height[i];
printf("%d\n", ans);
}
}

SPOJ 694的更多相关文章

  1. SPOJ 694. Distinct Substrings (后缀数组不相同的子串的个数)转

    694. Distinct Substrings Problem code: DISUBSTR   Given a string, we need to find the total number o ...

  2. spoj 694 求一个字符串中不同子串的个数

    SPOJ Problem Set (classical) 694. Distinct Substrings Problem code: DISUBSTR Given a string, we need ...

  3. spoj 694. Distinct Substrings 后缀数组求不同子串的个数

    题目链接:http://www.spoj.com/problems/DISUBSTR/ 思路: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照su ...

  4. spoj 694 705 不相同的子串的个数

    http://www.spoj.com/problems/SUBST1/ SUBST1 - New Distinct Substrings #suffix-array-8 Given a string ...

  5. SPOJ 694 Distinct Substrings

    Distinct Substrings Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on SPOJ. O ...

  6. 【SPOJ 694】Distinct Substrings 不相同的子串的个数

    不会FQ啊,没法评测啊,先存一下代码QAQ 2016-06-16神犇Menci帮我测过AC了,谢谢神犇Menci QwQ #include<cstdio> #include<cstr ...

  7. 后缀数组 SPOJ 694 Distinct Substrings

    题目链接 题意:给定一个字符串,求不相同的子串的个数 分析:我们能知道后缀之间相同的前缀的长度,如果所有的后缀按照 suffix(sa[0]), suffix(sa[1]), suffix(sa[2] ...

  8. SPOJ 694 (后缀数组) Distinct Substrings

    将所有后缀按照字典序排序后,每新加进来一个后缀,它将产生n - sa[i]个前缀.这里和小罗论文里边有点不太一样. height[i]为和字典序前一个的LCP,所以还要减去,最终累计n - sa[i] ...

  9. spoj 694(后缀数组)

    题意:求一个字符串的不重复子串的个数. 分析:对于下标为i的位置,能够产生的前缀子串个数为len-i(下标从0开始),对于与它字典序相邻的后缀产生的子串是重复的(就是他们的最长公共前缀),所以我们要减 ...

  10. Distinct Substrings - spoj 694(不重复子串个数)

    题目大意:RT   分析:练手题目....后缀数组确实很强大.....多理解height数组, 切勿使用模版,后缀数组本身就有很多细节,多犯错更有利理解这个算法.   代码如下: ========== ...

随机推荐

  1. 获取订单的product_id 和订单的数量

    php 获取订单的product_id 和相对id的数量 <?php foreach ($val->groupResults(2) as $key2=>$val2):?> &l ...

  2. 制作npm插件vue-toast-m实例练习

    制作npm插件vue-toast-m实例练习(消息弹窗) 一.使用npm插件 import VueToast from 'vue-toast-demo-cc' Vue.use(VueToast) th ...

  3. 21.Shiro在springboot与vue前后端分离项目里的session管理

    1.前言 当决定前端与后端代码分开部署时,发现shiro自带的session不起作用了. 然后通过对请求head的分析,然后在网上查找一部分解决方案. 最终就是,登录成功之后,前端接收到后端传回来的s ...

  4. oracle client安装与配置

    (一)安装Oracle client 环境:windows7 64-bit.oracle client 64-bit (1)解压client安装包 (2)双击setup.exe,选择管理员,一直nex ...

  5. Flask—02-Flask会话控制与模板引擎

    会话控制原理 说明:概念百度说明的很详细,请自行百度 cookie 说明: 由于HTTP协议无状态无连接的特点,导致一个用户在同一网站做连续操作时,需要不断的提供身份信息:为了解决这个问题,我们可以通 ...

  6. 基于 UIImagePickerController 的拓展封装 - iOS

    基于 UIImagePickerController 的拓展,分别支持调用相机.相册的功能,其中相机可以设置默认调用前后摄像头; 简单对此进行了封装和实现,其中还有很多点可以继续挖掘和优化,该版本具体 ...

  7. etcd客户端c#

    etcd是什么东西就不介绍了,自己网上搜索,简单说就是一个分布式K/V存储系统: 由于它是go语言写的,没有其它客户端,找到一个java的. 出于方案积累原因,写了c#版本,可以使用.c#版本是基于e ...

  8. 【SHOI2015】脑洞治疗仪(恶心的线段树,区间最大子段和)

    题目描述: 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个 01 序列.11代表这个位 ...

  9. dom4j里面封装方法的操作

    animal.xml <?xml version="1.0" encoding="UTF-8"?><animal>   <cat ...

  10. less学习一

    Less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量.Mixin.函数等特性,使 CSS 更易维护和扩展. Less 可以运行在 Node 或浏览器端. less文件只有被编译后才 ...