题面

题意:

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

多组数据。

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. HDU 1312 Red and Black(最简单也是最经典的搜索)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1312 Red and Black Time Limit: 2000/1000 MS (Java/Oth ...

  2. 我想写一个前端开发工具(一):在npm发布模块

    有必要说说我为什么要开始写这个,正文从下面的第一条开始 我最近忙于公司的项目,一直没有抽出时间来写文章.本来想每个月写一片文章,保质保量,无奈上个月没有坚持. 这段时间有点忙,主要是由于公司业务调整, ...

  3. Entity Framework 三

    DbContext:上下文 EDM将生成从System.Data.Entity.DbContext类派生的SchoolDBEntities类,如下所示.派生DbContext的类在实体框架中被称为上下 ...

  4. 封装全局icon组件 svg (仿造element-ui源码)

    一.引入  svg-sprite-loader 插件 npm install svg-sprite-loader --save-dev vue-cli项目默认情况下会使用 url-loader 对sv ...

  5. redis的安装和启动linux环境

    启动客户端连接redis服务,redis-cli -p(端口) -h(登录的服务的ip地址);不添加任何参数和选项直接使用redis-cli将会默认登录6379,默认使用ip 127.0.0.1#re ...

  6. nginx配置、域名、前端代码部署

    服务器上部署nginx,部署多个独立的代码,用nginx做域名映射的配置方法: 修改/usr/local/nginx/conf/nginx.conf文件,重点是最后一行,include /data/n ...

  7. 重写Alert和confirm方法去除地址显示

    //重写alert方法,去掉地址显示window.alert = function(name){var iframe = document.createElement("IFRAME&quo ...

  8. Javascript中的this对象

    对于this的使用,我们最常遇到的主要有,在全局函数中,在对象方法中,call和apply时,闭包中,箭头函数中以及class中: 我们知道this对象是在运行时基于函数的执行环境绑定的,在调用函数之 ...

  9. fabricjs 的用途

    使用html5 的canvas画板做一些图片旋转,拖动,放大,缩小和合成图片的功能,有没有一个集成好的组件库呢?答案肯定是有的,而且还不止我前面提到的功能,下面介绍一下我使用的fabricjs. 官网 ...

  10. MHA实现mysql高可用复制集群

    MHA简述 MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件.在My ...