题面

题意:

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

多组数据。

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. Hive中使用LZO

    hive 中使用lzo 1 启动hive 错误Exception in thread "main" java.lang.NoClassDefFoundError: org/apac ...

  2. Angularjs 数据循环

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  3. gcc扩展语法一:在表达式中的语句和声明

    在GNU C中包含在括号中的复合语句可以作为一个表达式.这就允许你在表达式中使用循环,switch和局部变量. 以前复合语句是包含在大括号中语句序列.在这种构造中,圆括号包围在大括号中.如下面的例子: ...

  4. Restrramework源码(包含组件)分析

    1.总体流程分析 rest_framework/view.py 请求通过url分发,触发as_view方法,该方法在ViewSetMixin类下 点进去查看as_view源码说明,可以看到它在正常情况 ...

  5. SpringBoot非官方教程 | 第二十六篇: sprinboot整合elk,搭建实时日志平台

    转载请标明出处: 原文首发于https://www.fangzhipeng.com/springboot/2017/07/11/sprinboot25-elk/ 本文出自方志朋的博客 这篇文章主要介绍 ...

  6. iOS之一些实用的Demo

    图像浏览及处理 FLAnimatedImage - gif播放处理的工具. CLImageEditor - 超强的图片编辑库,快速帮你实现旋转,防缩,滤镜等等一系列麻烦的事情. ios-image-f ...

  7. 『ACM C++』HDU杭电OJ | 1425 - sort (排序函数的特殊应用)

    今天真的是累哭了,周一课从早八点半一直上到晚九点半,整个人要虚脱的感觉,因为时间不太够鸭所以就回头看看找了一些比较有知识点的题来总结总结分析一下,明天有空了就开始继续打题,嘻嘻嘻. 今日兴趣电影: & ...

  8. Linux计算某一列的和

    ll | awk '{print $5}' | egrep -v "^$"| paste -sd+|bc 简单说明: ll:拿到当前目录下所有的文件大小 awk:拿到第几列 egr ...

  9. 构建高可靠hadoop集群之4-权限指引

    此文翻译自http://hadoop.apache.org/docs/r2.8.0/hadoop-project-dist/hadoop-hdfs/HdfsPermissionsGuide.html ...

  10. (转)Maven POM中的各种scope的行为总结

    原地址:https://blog.csdn.net/cnweike/article/details/52221410 compile:默认的scope.任何定义在compile scope下的依赖将会 ...