题目:Boring counting

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

题意:给一个字符串,问有多少子串出现过两次以上,重叠不能算两次,比如ababa,aba只出现一次。

思路:

  网上搜的题解估计大部分都是后缀数组,但字典树+优化是可以解决该问题的。

  字典树解决这题难点就是内存,先不考虑内存,那么可以遍历起始点,然后添加入字典树,比如现在abab要添加进字典树,如果原本已经存在abab,并且两个不重叠,那么ans++,同时将abab标记掉,如果不存在,记录此时的下标以便等会判断是否重叠。(很简单的思路。)

  现在解决内存,可以计算,如果要通过内存限制,字典树节点只能27万左右。但如果只设置这么大,最后会超出,会RE(G++好像会显示TLE),可以想象,字典树上很多节点的next[26]都是-1,浪费空间,因此可以把next[26]换成vector,动态申请,查找时多花一点时间遍历,但内存大大减小。

---------------------------------------------------------------------------------

  下面是后缀数组解决该问题的方法:

  首先要明白后缀数组里几个数组的用法,这里不详述了。

  首先,我们可以遍历满足要求的字串的长度len,从1 到ls/2,然后遍历一遍height数组,height[i]表示排名第i 的后缀和排名第i-1 的后缀的最长公共前缀长度,那么如果height[i]>=len,这就有可能是答案了,只要不重叠就可以了,重叠可以用sa数组判断,可以找出最左边的下标记为l,最右边的下标记为r,只要l+len<=r就可以了,注意,height<len以后就是另外的字符串了。

AC代码:

 #include<stdio.h>
#include<string.h>
#include<map>
#include<vector>
using namespace std;
struct Node
{
int val;
map<char,int> next;
}v[];
int vNum;
int ans;
void add(char *s,int start)
{
int p = ;
for(int i=start;s[i];i++)
{
int t = v[p].next[s[i]];
if(t!=) p = t;
else
{
v[vNum].val=-;
v[vNum].next.clear();
v[p].next[s[i]]=vNum++;
p=vNum-;
}
if(v[p].val!=-)
{
if(v[p].val!=- && v[p].val<start)
{
ans++;
v[p].val=-;
}
}
else v[p].val = i;
}
}
char s[];
int main()
{
while(~scanf("%s",s))
{
if(s[]=='#') break;
v[].val=-;
for(int i=;i<;i++) v[].next.clear();
vNum=;
ans=;
for(int i=;s[i];i++)
{
add(s,i);
}
printf("%d\n",ans);
}
return ;
}

字典树

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<map>
#include<list>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
#define N 1010
#define M 100010
#define Mod 1000000007
#define LL long long
#define INF 0x7fffffff
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
#define For(i,f_start,f_end) for(int i=f_start;i<f_end;i++)
#define REP(i,f_end,f_start) for(int i=f_end;i>=f_start;i--)
#define Rep(i,f_end,f_start) for(int i=f_end;i>f_start;i--)
#define MT(x,i) memset(x,i,sizeof(x))
#define gcd(x,y) __gcd(x,y)
const double PI = acos(-); char s1[];
int ws[N],wv[N];
int sa[N],r[N],wx[N],wy[N];
int height[N];
bool cmp(int *r,int a,int b,int l)
{
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void da(int *r,int n,int m)
{
int *x=wx,*y=wy;
for(int i=;i<m;i++) ws[i]=;
for(int i=;i<n;i++) ws[x[i]=r[i]]++;
for(int i=;i<m;i++) ws[i]+=ws[i-];
for(int i=n-;i>=;i--) sa[--ws[x[i]]]=i;
int i,j,p,*t;
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++;
}
for(int i=;i<n;i++)
{
r[sa[i]]=i;
}
}
void calHeight(int n)
{
int h=;
for(int i=;i<n;i++)
{
if(r[i]==) h=;
else
{
int k=sa[r[i]-];
if(--h<) h=;
while(s1[k+h]==s1[i+h]) h++;
}
height[r[i]]=h;
}
} int main()
{
while(~scanf("%s",s1))
{
if(s1[]=='#') break;
int ls = strlen(s1);
for(int i=;i<ls;i++)
{
r[i]=s1[i]-'a'+;
}
r[ls++]=;
da(r,ls,);
calHeight(ls);
int ans = ;
for(int i=;i<=(ls-)/;i++)
{
int flag = ;
int l=INF,r=-;
for(int j=;j<ls;j++)
{
if(height[j]>=i)
{
l = min(sa[j],min(sa[j-],l));
r = max(sa[j],max(sa[j-],r));
if(flag==&&l+i<=r)
{
ans++;
flag=;
}
}
else
{
flag=;
l=INF;
r=-;
}
}
}
printf("%d\n",ans);
}
return ;
}

后缀数组

HDU 3518 Boring counting的更多相关文章

  1. 后缀数组 --- HDU 3518 Boring counting

    Boring counting Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3518 Mean: 给你一个字符串,求:至少出 ...

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

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

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

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

  4. hdu 3518 Boring counting 后缀数组LCP

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

  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. Js的reduce()方法

    Js 数组reduce()方法应用一个函数针对数组的两个值(从左到右),以减至一个值. 语法:array.reduce(callback[, initialValue]) 参数说明: 1)callba ...

  2. 【eclipse】eclipse报错:the resource is not on the build path of a java project

    最近在eclipse中,使用svn导入svn上的一个maven项目,但是导入后类的包并没有以源码包的方式显示,而是以普通文件包的方式显示出来,在对类进行F3等操作时就报错:“the resource ...

  3. MySQL优化特定类型的查询

    优化关联查询 如果想要优化使用关联的查询,我们需要特别留意以下几点: 确保ON或者USING子句中的列上有索引.在创建索引的时候需要考虑到关联的顺序.当表A和表B用列c关联的时候,如果优化器的关联顺序 ...

  4. 浅谈ST表

    发现自己学的一直都是假的ST表QWQ. ST表 ST表的功能很简单 它是解决RMQ问题(区间最值问题)的一种强有力的工具 它可以做到$O(nlogn)$预处理,$O(1)$查询最值 算法 ST表是利用 ...

  5. Dynamics 365出现数据加密错误怎么办?

    本人微信公众号:微软动态CRM专家罗勇 ,回复290或者20181227可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . Dy ...

  6. 设计模式系列之过滤器模式(Chriteria Pattern)

    过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来.这种类 ...

  7. SpringBoot实现全文搜索

    • 全文搜索  • solr安装  • solr中文分词  • solr数据库导入  • solr数据查询  • solrj接口调用     1:

  8. redis的几种数据导入导出方式【转】

    环境说明:202.102.221.11 redis源实例202.102.221.12 redis目标实例202.102.221.13 任意linux系统 一.redis-dump方式 1.安装redi ...

  9. 【学习笔记】【Design idea】一、Java异常的设计思想、性能相关、笔记

    1.前言: 异常.本该是多么优雅的东西,然而,得全靠自己在零散的信息中汇集. 学习笔记保持更新. 2.教材(参考资料) 其他 ①受检异常与非受检异常:https://www.cnblogs.com/j ...

  10. MongoDB副本集功能及节点属性梳理

    副本集的主要功能 副本集是MongoDB高可用的基础,其主要作用 归纳为以下几点: (1)高可用,防止设备(服务器.网络)故障.提供自动FailOver功能. (2)无需配置高可用性虚拟节点:无论是S ...