Boring counting

Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3518


Mean:

给你一个字符串,求:至少出现了两次(无重叠)的子串的种类数。

analyse:

后缀数组中height数组的运用,一般这个数组用得很少。

总体思路:分组统计的思想:将相同前缀的后缀分在一个组,然后对于1到len/2的每一个固定长度进行统计ans。

首先我们先求一遍后缀数组,并把height数组求出来。height数组代表的含义是:字典序相邻(即rank数组相邻)的两个后缀的最长公共前缀的长度。

由于子串不能重叠,那么就可以确定出子串长度的取值范围:1~len/2。(维护sa[]的最大值和最小值是为了判断排名相邻两个字符串的距离是否大于k,只有大于k才能保证不重叠)。

接下来我们对1~len/2的每一个固定长度进行统计该长度的子串有多少种,一路累加即得答案。

关键是要理解使用height数组进行分组统计的过程。

Time complexity: O(nlogn)

Source code: 

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-05-09-21.22
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define LL long long
#define ULL unsigned long long
using namespace std;
const int MAXN=;
//以下为倍增算法求后缀数组
int wa[MAXN],wb[MAXN],wv[MAXN],Ws[MAXN];
int cmp(int *r,int a,int b,int l)
{return r[a]==r[b]&&r[a+l]==r[b+l];}
void da(const char *r,int *sa,int n,int m) //
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=;i<m;i++) Ws[i]=;
for(i=;i<n;i++) Ws[x[i]=r[i]]++;
for(i=;i<m;i++) Ws[i]+=Ws[i-];
for(i=n-;i>=;i--) sa[--Ws[x[i]]]=i;
for(j=,p=;p<n;j*=,m=p){
for(p=,i=n-j;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=;i<n;i++) wv[i]=x[y[i]];
for(i=;i<m;i++) Ws[i]=;
for(i=;i<n;i++) Ws[wv[i]]++;
for(i=;i<m;i++) Ws[i]+=Ws[i-];
for(i=n-;i>=;i--) sa[--Ws[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=,x[sa[]]=,i=;i<n;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p-:p++;
}
return;
}
int sa[MAXN],Rank[MAXN],height[MAXN];
//求height数组
void calheight(const char *r,int *sa,int n){
int i,j,k=;
for(i=;i<=n;i++) Rank[sa[i]]=i;
for(i=;i<n;height[Rank[i++]]=k)
for(k?k--:,j=sa[Rank[i]-];r[i+k]==r[j+k];k++);
return;
}
char str[MAXN];
int solve(int k,int len)
{
int maxx=,minn=INT_MAX,ans=;
for(int i=;i<=len;++i)
{
if(height[i]>=k)
maxx=max(maxx,max(sa[i-],sa[i])),minn=min(minn,min(sa[i-],sa[i]));
else
{
if(maxx-minn>=k) ans++;
maxx=,minn=INT_MAX;
}
}
if(maxx-minn>=k)ans++;
return ans;
}
int main()
{
while(~scanf("%s",str) && strcmp(str,"#")!=)
{
int len=strlen(str);
/**< 传入参数:str,sa,len+1,ASCII_MAX+1 */
da(str,sa,len+,);
/**< str,sa,len */
calheight(str,sa,len);
LL ans=;
for(int i=;i<=len/;++i)
ans+=solve(i,len);
cout<<ans<<endl;
}
return ;
}

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

  1. HDU 3518 Boring counting(后缀数组,字符处理)

    题目 参考自:http://blog.sina.com.cn/s/blog_64675f540100k9el.html 题目描述: 找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠). ...

  2. hdu 3518 Boring counting 后缀数组LCP

    题目链接 题意:给定长度为n(n <= 1000)的只含小写字母的字符串,问字符串子串不重叠出现最少两次的不同子串个数; input: aaaa ababcabb aaaaaa # output ...

  3. HDU 3518 Boring counting

    题目:Boring counting 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3518 题意:给一个字符串,问有多少子串出现过两次以上,重叠不能算两次 ...

  4. hdu 3518 Boring counting 后缀数组基础题

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...

  5. hdu 3518 Boring counting 后缀数组

    题目链接 根据height数组的性质分组计算. #include <iostream> #include <vector> #include <cstdio> #i ...

  6. hdu 3518 Boring counting 后缀数组 height分组

    题目链接 题意 对于给定的字符串,求有多少个 不重叠的子串 出现次数 \(\geq 2\). 思路 枚举子串长度 \(len\),以此作为分界值来对 \(height\) 值进行划分. 显然,对于每一 ...

  7. HDOJ 题目3518 Boring counting(后缀数组,求不重叠反复次数最少为2的子串种类数)

    Boring counting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  8. HDU 4358 Boring counting(莫队+DFS序+离散化)

    Boring counting Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others) ...

  9. HDU - 4358 Boring counting (dsu on tree)

    Boring counting: http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意: 求一棵树上,每个节点的子节点中,同一颜色出现k次 的 个数. 思 ...

随机推荐

  1. JAVA生产者消费者的实现

    春节回了趟老家,又体验了一次流水席,由于桌席多,导致上菜慢,于是在等待间,总结了一下出菜流程的几个特点: 1.有多个灶台,多个灶台都在同时做菜出来. 2.做出来的菜,会有专人用一个托盘端出来,每次端出 ...

  2. JXLS 双循环模板

    商户名称 门店代码 时间 金额 <jx:forEach items="${resultList}" var="l">       ${l.name} ...

  3. Android开发利器 - Charles + Genymotion 调试网络应用程序

    Charles默认是不监听Genymotion模拟器的网络动态的. 需要进行以下设置: 1. 打开你的Genymotion模拟器 2. 设置 -> Wifi -> 长按你的当前的网络连接 ...

  4. activemq安装与简单消息发送接收实例

    安装环境:Activemq5.11.1, jdk1.7(activemq5.11.1版本需要jdk升级到1.7),虚拟机: 192.168.147.131 [root@localhost softwa ...

  5. MVC使用基架添加控制器出现的错误:无法检索XXX的元数据

    环境 vs2012 框架 mvc3 数据库  sqlservercompact4.0 出现的错误如下: “ ---------------------------Microsoft Visual St ...

  6. ios开发中的Swift面向对象

    iOS在现代计算机语言中,面向对象是非常重要的特性,Swift语言也提供了面向对象的支持.而且在Swift语言中,不仅类具有面向对象特性,结构体和枚举也都具有面向对象特性. 1.Swift中的类和结构 ...

  7. Navi.Soft30.产品.Net对象查看器.操作手册

    1系统简介 1.1功能简述 在软件开发过程中,我们会编写各种类以及创建类的属性,方法,事件等.特别是第三方控件或组件,刚拿到手时,若没有完善的开发文档,很难下手.这时,若是可以查看这些DLL的成员对象 ...

  8. INSTALL MYSQL IN MAC

    安装好MYSQL后,在System References中找到MYSQL,启动它. 启动之后在终端中输入添加MySQL路径的命令,把MYSQL路径添加到PATH中: PATH="$PATH& ...

  9. [论文笔记] Methodologies for Data Quality Assessment and Improvement (ACM Comput.Surv, 2009) (1)

    Carlo Batini, Cinzia Cappiello, Chiara Francalanci, and Andrea Maurino. 2009. Methodologies for data ...

  10. Binary Tree Postorder Traversal--leetcode难题讲解系列

    https://leetcode.com/problems/binary-tree-postorder-traversal/ Given a binary tree, return the posto ...