题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3518

题意: 给出一个字符串, 问其中有多少字串出现了两次以上(计算次数时不能彼此覆盖, 如 "aaaa"  中 "aa" 出现了两次而非三次).

思路: 后缀数组/字典树

后缀数组解法, 题目所求即使用后缀中出现两次以上的前缀数目. 可以枚举前缀长度, 将满足条件的前缀累进答案中. 在 SA 数组中, 具有相同前缀的后缀肯定是在一个连续块中的. 可以用 height 数组的性质来区分当前长度有哪些前缀块. 注意满足条件的前缀块中至少存在两个彼此不覆盖的前缀.

代码:

 #include <iostream>
#include <stdio.h>
#include <string.h>
#define rank Rank
using namespace std; const int MAXN = 1e4 + ;
char str[MAXN];
int SA[MAXN], rank[MAXN], height[MAXN], sum[MAXN], tp[MAXN], a[MAXN]; bool cmp(int *f, int x, int y, int w){
return f[x] == f[y] && f[x + w] == f[y + w];
} void get_SA(int *s, int n, int m){
for(int i = ; i < m; i++) sum[i] = ;
for(int i = ; i < n; i++) sum[rank[i] = s[i]]++;
for(int i = ; i < m; i++) sum[i] += sum[i - ];
for(int i = n - ; i >= ; i--) SA[--sum[rank[i]]] = i;
for(int len = ; len <= n; len <<= ){
int p = ;
for(int i = n - len; i < n; i++) tp[p++] = i;//后面i个数没有第二关键字,即第二关键字为空,所以最小
for(int i = ; i < n; i++){
if(SA[i] >= len) tp[p++] = SA[i] - len;
}
//tp[i]存储按第二关键字排序第i的下标
//对第二关键字排序的结果再按第一关键字排序,和长度为1的情况类似
for(int i = ; i < m; i++) sum[i] = ;
for(int i = ; i < n; i++) sum[rank[tp[i]]]++;
for(int i = ; i < m; i++) sum[i] += sum[i - ];
for(int i = n - ; i >= ; i--) SA[--sum[rank[tp[i]]]] = tp[i];
//根据SA和rank数组重新计算rank数组
swap(rank, tp);//交换后tp指向旧的rank数组
p = ;
rank[SA[]] = ;
for(int i = ; i < n; i++){
rank[SA[i]] = cmp(tp, SA[i - ], SA[i], len) ? p - : p++;
}
if(p >= n) break;
m = p;//下次基数排序的最大值
}
//求height
int k = ;
n--;
for(int i = ; i <= n; i++) rank[SA[i]] = i;
for(int i = ; i < n; i++){
if(k) k--;
int j = SA[rank[i] - ];
while(s[i + k] == s[j + k]) k++;
height[rank[i]] = k;
}
} int main(void){
while(~scanf("%s", str)){
if(str[] == '#') break;
int len = strlen(str), sol = ;
for(int i = ; i < len; i++) a[i] = str[i];
a[len] = ;
get_SA(a, len + , );
for(int i = ; i <= len / ; i++){
int l = MAXN, r = ;
for(int j = ; j <= len; j++){
if(height[j] >= i){
l = min(l, min(SA[j], SA[j - ]));
r = max(r, max(SA[j], SA[j - ]));
}else{
if(r - l >= i) sol++;
l = MAXN;
r = ;
}
}
if(r - l >= i) sol++;
}
printf("%d\n", sol);
}
return ;
}

hdu3518(后缀数组)的更多相关文章

  1. HDU3518 后缀数组求不可重叠重复出现的不同子串个数

    枚举子串长度,根据height分组,如果本组sa最小值与sa最大值之差超过枚举的长度,则本组对于答案贡献为1. #include <iostream> #include <vecto ...

  2. hdu3518 Boring counting(后缀数组)

    Boring counting 题目传送门 解题思路 后缀数组.枚举每种长度,对于每个字符串,记录其最大起始位置和最小起始位置,比较是否重合. 代码如下 #include <bits/stdc+ ...

  3. poj 2774 Long Long Message 后缀数组基础题

    Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 24756   Accepted: 10130 Case Time Limi ...

  4. 后缀数组的倍增算法(Prefix Doubling)

    后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...

  5. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  6. BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]

    1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1383  Solved: 582[Submit][St ...

  7. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  8. POJ1743 Musical Theme [后缀数组]

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 27539   Accepted: 9290 De ...

  9. 后缀数组(suffix array)详解

    写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具. 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料. 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, ...

随机推荐

  1. Mina APR传输与串口传输讲解---zhengli

    原文地址:Mina Transports(Apache Mina user guide Chapter6 Transport) 1.1.1.APR传输 1.1.1.1.介绍 APR (Apache P ...

  2. Oracle logminer 分析redo log(TOAD与PLSQL)

    Oracle logminer 分析redo log Oracle 11g r2 RAC centos 6.5 设置时间格式 select to_char(sysdate,'yyyy-mm-dd hh ...

  3. 用IntelliJ IDEA建maven项目,如何解决main下无法创建java源文件

    一.缺少java源文件 如下图: 现在想要在main下面增加java源文件,效果图如下所示: 首先,在main目录下新建java文件夹,就是源文件目录, 然后,右键,选择Mark Directory ...

  4. MySQL执行计划的讲解

    最近同事在执行线上执行一条MySQL的查询语句,数据的话在9000条左右,但使用左连接的时候查询速度大概在15秒左右~这速度确实是无法接受的~ 经过简单的修改,变为内连接的话,执行速度不到1秒. 下面 ...

  5. java线程游戏之背景图片的移动

    package com.plane; import java.awt.Graphics; import java.awt.Image; import javax.swing.ImageIcon; im ...

  6. JAVA基础知识总结9(特殊类)

    1.Object: 所有类的直接或者间接父类,Java认为所有的对象都具备一些基本的共性内容,这些内容可以不断的向上抽取,最终就抽取到了一个最顶层的类中的,该类中定义的就是所有对象都具备的功能. 具体 ...

  7. VS2012新建网站出现(1)的解决方案

    1.用记事本打开以下文件: D:\Users\lyn\Documents\IISExpress\config\applicationhost.config 2.删除sites结点下的所有site结点:

  8. 修改Win10默认窗口背景色为护眼色的方法

    按Windows键+R,打开“运行”对话框,输入regedit: 修改[HKEY_CURRENT_USER\Control Panel\Colors]下Windows键值为 199 237 204, ...

  9. [转]SQL 模糊查询

      在进行数据库查询时,有完整查询和模糊查询之分. 一般模糊查询语句如下: SELECT 字段 FROM 表 WHERE 某字段 Like 条件 其中关于条件,SQL提供了四种匹配模式: 1,% :表 ...

  10. Ajax01 什么是ajax、获取ajax对象、ajax对象的属性和方法、编程步骤、缓存问题、乱码问题

    目录 1 什么是ajax 2 获取ajax对象 3 ajax对象的属性和方法 4 使用ajax的编程步骤 5 缓存问题 6 乱码问题 1 什么是ajax ajax是一种用来改善用户体验的技术,其本质是 ...