hdu1403(后缀数组模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1403
题意: 给出两个字符串, 求他们的最长公共子串
思路: 两个字符串的最长公共子串长度显然就是两个字符串的所有后缀中的最长公共前缀长度. 可以先用一个没有出现的字符(便于后面区分后缀是否属于相同字符串)将两个字符串连成一个字符串,再用后缀数组求其height, SA数组, 对于当前 i, 通过 SA 数组区分后缀 i 和 i - 1 是否在同一个初始字符串中, 若不是则用 height[i] 维护答案最大值.
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rank Rank
using namespace std; const int MAXN = 2e5 + ; char str[MAXN];
int SA[MAXN], rank[MAXN], height[MAXN], sum[MAXN], tp[MAXN];
//rank[i] 第i个后缀的排名, SA[i] 排名为i的后缀的位置, Height[i] 排名为i的后缀与排名为(i-1)的后缀的LCP
//sum[i] 基数排序辅助数组, 存储小于i的元素有多少个, tp[i] rank的辅助数组(按第二关键字排序的结果),与SA意义一样 bool cmp(int *f, int x, int y, int w){
return f[x] == f[y] && f[x + w] == f[y + w];
} void get_SA(char *s, int n, int m){
//先预处理长度为1的情况
for(int i = ; i < m; i++) sum[i] = ;//清0
for(int i = ; i < n; i++) sum[rank[i] = s[i]]++;//统计每个字符出现的次数
for(int i = ; i < m; i++) sum[i] += sum[i - ];//sum[i]为小于等于i的元素的数目
for(int i = n - ; i >= ; i--) SA[--sum[rank[i]]] = i;//下标从0开始,所以先自减
//SA[i]存储排名第i的后缀下标,SA[--sum[rank[i]]] = i 即下标为i的后缀排名为--sum[rank[i]],这很显然
for(int len = ; len <= n; len <<= ){
int p = ;
//直接用SA数组对第二关键字排序
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++;//注意判定rank[i]和rank[i-1]是否相等
}
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){
char str[MAXN];
while(~scanf("%s", str)){
int len = strlen(str);
str[len] = '';
scanf("%s", str + len + );
int n = strlen(str);
str[n] = ; //末尾添加一个0
get_SA(str, n + , 'z' + );
int sol = ;
for(int i = ; i < n; i++){
if(SA[i] > len && SA[i - ] < len) sol = max(sol, height[i]);
if(SA[i] < len && SA[i - ] > len) sol = max(sol, height[i]);
}
printf("%d\n", sol);
}
return ;
}
hdu1403(后缀数组模板)的更多相关文章
- BZOJ 1031 [JSOI2007]字符加密Cipher | 后缀数组模板题
BZOJ 1031 [JSOI2007]字符加密Cipher | 后缀数组模板题 将字符串复制一遍接在原串后面,然后后缀排序即可. #include <cmath> #include &l ...
- POJ 2774 Long Long Message 后缀数组模板题
题意 给定字符串A.B,求其最长公共子串 后缀数组模板题,求出height数组,判断sa[i]与sa[i-1]是否分属字符串A.B,统计答案即可. #include <cstdio> #i ...
- 后缀数组模板/LCP模板
//后缀数组模板,MANX为数组的大小 //支持的操作有计算后缀数组(sa数组), 计算相邻两元素的最长公共前缀(height数组),使用get_height(); //计算两个后缀a, 和b的最长公 ...
- 洛谷:P3809 【模板】后缀排序(后缀数组模板)
P3809 [模板]后缀排序 题目链接:https://www.luogu.org/problemnew/show/P3809 题目背景 这是一道模板题. 题目描述 读入一个长度为 nn 的由大小写英 ...
- 【Luogu】P3809后缀排序(后缀数组模板)
题目链接 今天终于学会了后缀数组模板qwq 不过只会模板emmmm 首先我们有一本蓝书emmmmmm 然后看到蓝书221页代码之后我就看不懂了 于是请出rqy rqy: 一开始那是个对单个字符排序的操 ...
- 【BZOJ 1031】[JSOI2007]字符加密Cipher(后缀数组模板)
[题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1031 [题意] [题解] 后缀数组模板题; 把整个字符串扩大一倍. 即长度乘2 然后搞 ...
- 后缀数组 模板题 hdu1403(最长公共(连续)子串)
好气啊,今天没有看懂后缀树和后缀自动机 只能写个后缀数组发泄一下了orz #include <cstdio> #include <cstring> *; int wa[N], ...
- 【UOJ #35】后缀排序 后缀数组模板
http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...
- POJ2774 & 后缀数组模板题
题意: 求两个字符串的LCP SOL: 模板题.连一起搞一搞就好了...主要是记录一下做(sha)题(bi)过程心(cao)得(dan)体(xin)会(qing) 后缀数组概念...还算是简单的,过程 ...
随机推荐
- SpringBoot自动化配置之四:SpringBoot 之Starter(自动配置)、Command-line runners
Spring Boot Starter是在SpringBoot组件中被提出来的一种概念,stackoverflow上面已经有人概括了这个starter是什么东西,想看完整的回答戳这里 Starter ...
- MFC简单的橡皮筋程序
void CMainWindow::OnLButtonDown(UINT nFlags,CPoint point) { //以下三个是在CMainWindow中定义 m_ptFrom=point; m ...
- _tprintf(), printf(),wprintf() 与控制字符 %s 和 %S(Unicoe与GB2312))
_tprintf() 是 printf() 和 wprintf() 的通用类型:如果定义了 _unicode,那么 _tprintf() 就会转换为 wprintf(),否则为 printf() . ...
- C#高级参数out的使用
C#中有三个高级参数,分别是out,ref,params.本文章中先来介绍out参数的使用. out,用于在方法中返回多余值.(可以理解为让一个方法返回不同的类型值) 我们通过例子来理解例子的功能:用 ...
- eclipse中创建maven web项目
本文主要说明将maven web项目转成eclipse支持的web项目. 创建一个maven项目设置打包类型为war则其为web项目 结构如下 将mavenweb项目转成eclipse识别的web项目 ...
- Android基础学习:Android环境搭建
在3年前,自学过Android的一些基础知识,但是那个时候Linux等其他的知识结构比较薄弱,理解得不是很深刻,后来因项目变动的原因,没有再搞Android相关的东西了.时过境迁,还是因为项目变动,重 ...
- SSM项目连接远程Linux服务器的mysql 启动tomcat卡在了 Initializing Spring root WebApplicationContext
网上查了原因, linux下mysql访问速度缓慢并且ssh连接缓慢的原因 解决办法: 1.linux ssh连接慢 最近发现ssh连接的时候却很慢,ping的速度非常好,让人误以为是ssh连接不上. ...
- [转]怎么学习前端,尤其是 JavaScript 这块
1. 先看看 w3school ,了解什么是 js,再找几本写 js 小效果的书看看,知道 js 干什么: 2. 然后再去通读 API,推荐 <Javascript权威指南>,第四版吧,第 ...
- php中用大括号把?>和<?php框起来的作用
<?php function my_function() { ?> My function was called <!--就是这里,为什么前面要用?>和< ?php 把M ...
- 在Mac OS里安装和升级Git
在此记录,给自己看,也给别人参考. 进入终端,查看当前Git版本,输入指令:git --version 输入which git回车,可以查看当前git在什么位置 经查,版本:2.10.0,版本较低,为 ...