当前位置: 首页 > news >正文

后缀数组 --- 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=1010;
//以下为倍增算法求后缀数组
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=0;i<m;i++) Ws[i]=0;
    for(i=0;i<n;i++) Ws[x[i]=r[i]]++;
    for(i=1;i<m;i++) Ws[i]+=Ws[i-1];
    for(i=n-1;i>=0;i--) sa[--Ws[x[i]]]=i;
    for(j=1,p=1;p<n;j*=2,m=p){
        for(p=0,i=n-j;i<n;i++) y[p++]=i;
        for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
        for(i=0;i<n;i++) wv[i]=x[y[i]];
        for(i=0;i<m;i++) Ws[i]=0;
        for(i=0;i<n;i++) Ws[wv[i]]++;
        for(i=1;i<m;i++) Ws[i]+=Ws[i-1];
        for(i=n-1;i>=0;i--) sa[--Ws[wv[i]]]=y[i];
        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
    return;
}
int sa[MAXN],Rank[MAXN],height[MAXN];
//求height数组
void calheight(const char *r,int *sa,int n){
    int i,j,k=0;
    for(i=1;i<=n;i++) Rank[sa[i]]=i;
    for(i=0;i<n;height[Rank[i++]]=k)
        for(k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);
    return;
}
char str[MAXN];
int solve(int k,int len)
{
        int maxx=0,minn=INT_MAX,ans=0;
        for(int i=1;i<=len;++i)
        {
                if(height[i]>=k)
                        maxx=max(maxx,max(sa[i-1],sa[i])),minn=min(minn,min(sa[i-1],sa[i]));
                else
                {
                        if(maxx-minn>=k) ans++;
                        maxx=0,minn=INT_MAX;
                }
        }
        if(maxx-minn>=k)ans++;
        return ans;
}
int main()
{
        while(~scanf("%s",str) && strcmp(str,"#")!=0)
        {
                int len=strlen(str);
                /**< 传入参数:str,sa,len+1,ASCII_MAX+1 */
                da(str,sa,len+1,130);
                /**< str,sa,len */
                calheight(str,sa,len);
                LL ans=0;
                for(int i=1;i<=len/2;++i)
                        ans+=solve(i,len);
                cout<<ans<<endl;
        }
        return 0;
}
View Code

 

转载于:https://www.cnblogs.com/crazyacking/p/4490844.html

相关文章:

  • C++语言基础 例程 基类与派生类的转换
  • CDA数据分析师认证考试模拟题库
  • CDH使用之CM 5.3.x安装
  • STM32 ~ 如何从ST网站找到对应的固件库
  • [裴礼文数学分析中的典型问题与方法习题参考解答]5.1.12
  • [裴礼文数学分析中的典型问题与方法习题参考解答]5.1.16
  • (笔试题)分解质因式
  • 【Git使用具体解释】EGit使用具体解释
  • HttpWebResponse类
  • python 读取目录文件
  • 从30岁到35岁:为你的生命多积累一些厚度
  • 基于VLC的视频播放器
  • [HTTP]HTTP协议的状态码
  • 福州大学第十一届程序设计竞赛
  • Android sendToTarget
  • github指令
  • java中具有继承关系的类及其对象初始化顺序
  • laravel 用artisan创建自己的模板
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Python连接Oracle
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 入门到放弃node系列之Hello Word篇
  • 微服务核心架构梳理
  • 小而合理的前端理论:rscss和rsjs
  • RDS-Mysql 物理备份恢复到本地数据库上
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • ​Spring Boot 分片上传文件
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (二)JAVA使用POI操作excel
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (规划)24届春招和25届暑假实习路线准备规划
  • (汇总)os模块以及shutil模块对文件的操作
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (顺序)容器的好伴侣 --- 容器适配器
  • **PHP二维数组遍历时同时赋值
  • .java 9 找不到符号_java找不到符号
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .netcore 获取appsettings
  • .NET中GET与SET的用法
  • [ 手记 ] 关于tomcat开机启动设置问题
  • [2019.3.5]BZOJ1934 [Shoi2007]Vote 善意的投票
  • [8481302]博弈论 斯坦福game theory stanford week 1
  • [AIGC] MySQL存储引擎详解
  • [Android Pro] listView和GridView的item设置的高度和宽度不起作用
  • [AR]Vumark(下一代条形码)
  • [bzoj 3534][Sdoi2014] 重建
  • [CentOs7]搭建ftp服务器(2)——添加用户