SPOJ 694
题意:
给一个字符串,求它有多少个不同的子串
多组数据。
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的更多相关文章
- SPOJ 694. Distinct Substrings (后缀数组不相同的子串的个数)转
694. Distinct Substrings Problem code: DISUBSTR Given a string, we need to find the total number o ...
- spoj 694 求一个字符串中不同子串的个数
SPOJ Problem Set (classical) 694. Distinct Substrings Problem code: DISUBSTR Given a string, we need ...
- spoj 694. Distinct Substrings 后缀数组求不同子串的个数
题目链接:http://www.spoj.com/problems/DISUBSTR/ 思路: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照su ...
- spoj 694 705 不相同的子串的个数
http://www.spoj.com/problems/SUBST1/ SUBST1 - New Distinct Substrings #suffix-array-8 Given a string ...
- SPOJ 694 Distinct Substrings
Distinct Substrings Time Limit: 1000ms Memory Limit: 262144KB This problem will be judged on SPOJ. O ...
- 【SPOJ 694】Distinct Substrings 不相同的子串的个数
不会FQ啊,没法评测啊,先存一下代码QAQ 2016-06-16神犇Menci帮我测过AC了,谢谢神犇Menci QwQ #include<cstdio> #include<cstr ...
- 后缀数组 SPOJ 694 Distinct Substrings
题目链接 题意:给定一个字符串,求不相同的子串的个数 分析:我们能知道后缀之间相同的前缀的长度,如果所有的后缀按照 suffix(sa[0]), suffix(sa[1]), suffix(sa[2] ...
- SPOJ 694 (后缀数组) Distinct Substrings
将所有后缀按照字典序排序后,每新加进来一个后缀,它将产生n - sa[i]个前缀.这里和小罗论文里边有点不太一样. height[i]为和字典序前一个的LCP,所以还要减去,最终累计n - sa[i] ...
- spoj 694(后缀数组)
题意:求一个字符串的不重复子串的个数. 分析:对于下标为i的位置,能够产生的前缀子串个数为len-i(下标从0开始),对于与它字典序相邻的后缀产生的子串是重复的(就是他们的最长公共前缀),所以我们要减 ...
- Distinct Substrings - spoj 694(不重复子串个数)
题目大意:RT 分析:练手题目....后缀数组确实很强大.....多理解height数组, 切勿使用模版,后缀数组本身就有很多细节,多犯错更有利理解这个算法. 代码如下: ========== ...
随机推荐
- 【luogu P3366 最小生成树】 模板
这里是kruskal做法 当然prim也可以,至于prim和kruskal的比较: Prim在稠密图中比Kruskal优,Kruskal在稀疏图中比Prim优. #include<bits/st ...
- 线段tree~讲解+例题
最近学习了线段树这一重要的数据结构,有些许感触.所以写一篇博客来解释一下线段树,既是对自己学习成果的检验,也希望可以给刚入门线段树的同学们一点点建议. 首先声明一点,本人是个蒟蒻,如果在博客中有什么不 ...
- 【题解】洛谷P3399 丝绸之路
我丑,话说在前头 题目: https://www.luogu.org/problemnew/show/P3399 一道挺简单的DP 思路不难想 但是蒟蒻总是写错初始化啥的 思路 定义f[i][j]为第 ...
- ipython notebook开通远程
之前只是会用,别人告诉我命令和大概怎么设置的,今天自己搭建才发现一知半解搞不定啊. 目的:远程通过ipython notebook调用服务器. 服务器是ubuntu16.04 本地机器win7 配置方 ...
- linux系统命令与常识
之前短期学过linux,用到时才发现已经忘得一干二净了. 现在对学过的和了解到的做一个总结: 先明确一些使用工具: winscp : WinSCP是一个Windows环境下使用SSH的开源图形化SFT ...
- ATK 设计框架 之 Atk.CustomExpression
在ATK-DataPortal框架中的xxxHandel中常用到的一种类型,形如: 1.protected virtual D ItemHandle(D item, Func<E, E> ...
- Navicat for Mysql修改MySQL数据库密码,图文详解
1.创建一个连接 2.打开连接 3.按照图示123依次点击 4.输入新密码 5.查看实现修改密码功能的SQL语句(此步骤非必须) 6.最关键的一步:点击保存 7.出现如下现象,恭喜你,修改密码成功! ...
- go 下面定义嵌套结构
package main import ( "fmt" ) const ( URL = "http://www.163.com" UID = "adm ...
- ajax在同一页面中同控制器不同方法中调用数据并异步刷新的实例
我在实习以来都有做一些笔记,之前做的笔记都在简书里,现在我提前把公司给我的任务做好了,坐在电脑前又不好玩别的,那么我就整理下我之前的笔记吧!(此项目是thinkphp5开发的) 先上效果图 这是整体页 ...
- 【mvrp多协议vlan注册协议给予三种注册方式的验证】
MVRP 多vlan注册协议给予三种注册模式的配置 一:根据项目需求搭建好拓扑图如下 二:配置: 首先对项目做理论分析,sw1,sw2,sw3所组成的直连网络中,为使不同的PC之间进行通信,按vlan ...