Boring counting

\[Time Limit: 1000 ms \quad Memory Limit: 32768 kB
\]

题意

给出一个字符串,求出其中出现两次及以上的子串个数,要求子串之间不可以重合。

思路

对字符串后缀数组,然后枚举子串长度 \(len\),若某一段连续的 \(sa[i]\) 的 \(lcp \geq len\),那么说明这一段内存在一个长度为 \(lcp\) 的子串,而我们只需要其中的前 \(len\) 部分,接下来只要找出这个子串出现的最左和最右位置,然后判断中间能否放下这个长度为 \(len\) 的子串就可以了,如果可以的话,就让 \(ans\)++。


\(Hint\)

这题还让我学到后缀数组的另一个细节,在构建后缀数组之前,要在末尾加上一个比所有字符都小的字符,因为在求 \(height\) 的时候需要判断 \(a[i+k]==a[j+k]\),否则这里可能会无限扩展下去。

/***************************************************************
> File Name : a.cpp
> Author : Jiaaaaaaaqi
> Created Time : 2019年05月23日 星期四 22时40分17秒
***************************************************************/ #include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int> typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 1e5 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std; int n, m;
int cas, tol, T; char s[maxn];
int a[maxn], sa[maxn], tp[maxn], tax[maxn], rk[maxn], height[maxn]; void rsort(int n, int m) {
for(int i=0; i<=m; i++) tax[i] = 0;
for(int i=1; i<=n; i++) tax[rk[tp[i]]]++;
for(int i=1; i<=m; i++) tax[i] += tax[i-1];
for(int i=n; i>=1; i--) sa[tax[rk[tp[i]]]--] = tp[i];
} int cmp(int *f, int x, int y, int w) {
return f[x]==f[y] && f[x+w]==f[y+w];
} void SA(int *a, int n, int m) {
for(int i=1; i<=n; i++) rk[i] = a[i], tp[i] = i;
rsort(n, m);
for(int w=1, p=1, i; p<n; w<<=1, m=p) {
for(p=0, i=n-w+1; i<=n; i++) tp[++p] = i;
for(i=1; i<=n; i++) if(sa[i] > w) tp[++p] = sa[i]-w;
rsort(n, m), swap(rk, tp);
rk[sa[1]] = p = 1;
for(i=2; i<=n; i++) rk[sa[i]] = cmp(tp, sa[i], sa[i-1], w) ? p : ++p;
}
int j, k=0;
for(int i=1; i<=n; height[rk[i++]] = k)
for(k = k ? k-1 : k, j=sa[rk[i]-1]; a[i+k]==a[j+k]; k++);
} int calc(int len) {
int ans = 0;
int mx, mn;
mx = -inf, mn = inf;
for(int i=2; i<=n; i++) {
if(height[i]>=len) {
mx = max(mx, max(sa[i], sa[i-1]));
mn = min(mn, min(sa[i], sa[i-1]));
} else {
if(mx - mn >= len) ans++;
mx = -inf, mn = inf;
}
}
if(mx - mn >= len) ans++;
return ans;
} int main() {
while(scanf("%s", s+1)) {
if(s[1] == '#') break;
n = strlen(s+1);
s[++n] = 2;
for(int i=1; i<=n; i++) {
a[i] = s[i];
}
SA(a, n, 260);
// for(int i=1; i<=n; i++) {
// printf("sa[%d] = %d\n", i, sa[i]);
// }
int ans = 0;
for(int i=1; i<=(n+1)/2; i++) {
ans += calc(i);
}
printf("%d\n", ans);
}
return 0;
}

Boring counting HDU - 3518 (后缀数组)的更多相关文章

  1. Boring counting HDU - 3518 后缀自动机

    题意: 对于给出的字符串S, 长度不超过1000, 求其中本质不同的子串的数量, 这些子串满足在字符串S中出现了至少不重合的2次 题解: 将串放入后缀自动机中然后求出每一个节点对应的子串为后缀的子串出 ...

  2. Boring counting HDU - 3518 (后缀自动机)

    Boring counting \[ Time Limit: 1000 ms \quad Memory Limit: 32768 kB \] 题意 给出一个字符串,求出其中出现两次及以上的子串个数,要 ...

  3. hdu 3518(后缀数组)

    题意:容易理解... 分析:这是我做的后缀数组第一题,做这个题只需要知道后缀数组中height数组代表的是什么就差不多会做了,height[i]表示排名第i的后缀与排名第i-1的后缀的最长公共前缀,然 ...

  4. hdu 3948 后缀数组

    The Number of Palindromes Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (J ...

  5. HDU - 3948 后缀数组+Manacher

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3948 题意:给定一个字符串,求字符串本质不同的回文子串个数. 思路:主要参考该篇解题报告 先按照man ...

  6. HDU 5769 后缀数组

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5769 [2016多校contest-4] 题意:给定一个字符,还有一个字符串,问这个字符串存在多少个不 ...

  7. HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...

  8. hdu 2459 (后缀数组+RMQ)

    题意:让你求一个串中连续重复次数最多的串(不重叠),如果重复的次数一样多的话就输出字典序小的那一串. 分析:有一道比这个简单一些的题spoj 687, 假设一个长度为l的子串重复出现两次,那么它必然会 ...

  9. hdu 5442 (后缀数组)

    稍微学习了下第一次用后缀数组- - , 强行凑出答案 , 感觉现在最大的问题是很多算法都不知道 ,导致有的题一点头绪都没有(就像本题).  /*推荐 <后缀数组——处理字符串的有力工具>— ...

随机推荐

  1. VBA对象模型

    https://www.processon.com/view/link/5d974da6e4b07a0a4d4a098a

  2. Replication:Distribution Reader

    在transactional replication中,在publication中执行了一个更新,例如:update table set col=? Where ?,如果table中含有大量的数据行, ...

  3. Mysql系列(一)—— 基于5.7.22 解压版下载、安装、配置和卸载

    1.下载 从官网中直接获取自己想要的版本: MySQL Community Server 5.7.22 2.解压 将下载到的文件解压缩到自己喜欢的位置. 与mysql 5.6不同的是5.7版本中没有d ...

  4. laravel 5.5 仓库模式 文件之间接口与实现操作

    仓库模式 最直接的意思就是: Eloquent数据(数据库)查询  方便快捷,简单明了.自己怎么写的,就怎么去调用,完全ok~ 本质意思: 仓库就像是业务内部的数据对象集合,负责协调业务和数据映射层之 ...

  5. BAPI_TRANSACTION_COMMIT

    通过NCO执行SAP里面的 BAPI_TRANSACTION_COMMIT 并不能直接生效,类似SQL 里面的事物一样,需要有开始与结束,正确的方式如下: RfcSessionManager.Begi ...

  6. 【转】Webpack 快速上手(下)

    由于文章篇幅较长,为了更好的阅读体验,本文分为上.中.下三篇: 上篇介绍了什么是 webpack,为什么需要 webpack,webpack 的文件输入和输出 中篇介绍了 webpack 在输入和输出 ...

  7. npm升级到最新版本、指定版本

    npm 升级到最新版本 //linux下 npm install -g npm npm升级到指定版本 //比如升级到5.6.0 npm install -g npm@5.6.0

  8. 服务网格Istio初探

    1. 服务网格Istio初探 1.1. 什么是Istio 它是一个完全开源的服务网格.什么是服务网格? 这个术语通常用于描述构成这些应用程序的微服务网络以及应用之间的交互.随着规模和复杂性的增长,服务 ...

  9. 编写可维护的JavaScript-随笔(三)

    UI层的松耦合 本章提出了一个概念就是耦合 假设修改一个组件的时候需要修改很多其他的组件的话则表示组件之间存在紧耦合 如果修改一个组件而不需要修改其他组件的时候就做到了松耦合 页面是由HTML.CSS ...

  10. 安全SECUERITY单词SECUERITY证券

    中文名:证券业 外文名:secuerity 含义:指从事证券发行和交易服务 性质:证券市场的基本组成要素 组成:证券交易所.证券公司 目录 1 证券评级 2 证券定义 ? 涵义 ? 内容 ? 分类 ? ...