后缀数组 --- HDU 3518 Boring counting
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的更多相关文章
- HDU 3518 Boring counting(后缀数组,字符处理)
题目 参考自:http://blog.sina.com.cn/s/blog_64675f540100k9el.html 题目描述: 找出一个字符串中至少重复出现两次的字串的个数(重复出现时不能重叠). ...
- hdu 3518 Boring counting 后缀数组LCP
题目链接 题意:给定长度为n(n <= 1000)的只含小写字母的字符串,问字符串子串不重叠出现最少两次的不同子串个数; input: aaaa ababcabb aaaaaa # output ...
- HDU 3518 Boring counting
题目:Boring counting 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3518 题意:给一个字符串,问有多少子串出现过两次以上,重叠不能算两次 ...
- hdu 3518 Boring counting 后缀数组基础题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- hdu 3518 Boring counting 后缀数组
题目链接 根据height数组的性质分组计算. #include <iostream> #include <vector> #include <cstdio> #i ...
- hdu 3518 Boring counting 后缀数组 height分组
题目链接 题意 对于给定的字符串,求有多少个 不重叠的子串 出现次数 \(\geq 2\). 思路 枚举子串长度 \(len\),以此作为分界值来对 \(height\) 值进行划分. 显然,对于每一 ...
- HDOJ 题目3518 Boring counting(后缀数组,求不重叠反复次数最少为2的子串种类数)
Boring counting Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- HDU 4358 Boring counting(莫队+DFS序+离散化)
Boring counting Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others) ...
- HDU - 4358 Boring counting (dsu on tree)
Boring counting: http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意: 求一棵树上,每个节点的子节点中,同一颜色出现k次 的 个数. 思 ...
随机推荐
- 解决Electron加载带jquery的项目报错问题
<!-- Insert this line above script imports --> <script>if (typeof module === 'object') { ...
- Porter/Duff,图片加遮罩setColorFilter
同步发表于http://avenwu.net/2015/02/03/porterduff Fork on github https://github.com/avenwu/support 经常会遇到给 ...
- 用户管理 之 Linux 用户(User)查询篇
用户(User)和用户组(Group)的配置文件,是系统管理员最应该了解和掌握的系统基础文件之一,从另一方面来说,了解这些文件也是系统安全管理的重要组成部份:做为一个合格的系统管理员应该对用户和用户组 ...
- OAuth2.0和SSO授权
一.OAuth2.0授权协议 一种安全的登陆协议,用户提交的账户密码不提交到本APP,而是提交到授权服务器,待服务器确认后,返回本APP一个访问令牌,本APP即可用该访问令牌访问资源服务器的资源.由于 ...
- EF 5.0 帮助类
EF 5.0 帮助类 加入命名空间: using System; using System.Data; using System.Data.Entity; using System.Data.Enti ...
- 计算A/3,不用除法
int DividedBy3(int A) { ; ; i <= ; i += ) p += A << i; return (-p); }
- ikvm.net简介
ikvm.net是什么 http://www.ikvm.net/ ikvm.net是能够运行在mono和.net framework的java虚拟机.它包括了 在.net中实现的一个java虚拟机 j ...
- windows 获取以及更改CMD控制台编码[转]
本文转自 http://blog.sina.com.cn/s/blog_794b1d96010136yy.html 命令 chcp 功能:显示或设置活动代码页编号 CHCP [nnn] nnn ...
- 谷歌面经 Tree Serialization
http://www.careercup.com/question?id=4868040812396544 You should transform an structure of multiple ...
- 如何在Xcode6中添加空模板
在Xcode中模板位置: Macintosh HD ▸ 应用程序 ▸ Xcode(低于版本6的).app ▸ Contents ▸ Developer ▸ Platforms ▸ iPhoneOS.p ...