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) 后缀数组概念...还算是简单的,过程 ...
随机推荐
- Java栈,队列,优先队列的使用
1. 栈的使用: import java.util.*; public class Main{ public static void main(String[] args){ Deque<Str ...
- Hot resize Multipath Disk – Linux
This post is for the users of the great dm-multipath system in Linux, who encounter a major availabi ...
- 杂项:MIME(多用途互联网邮件扩展类型)百科
ylbtech-杂项:MIME(多用途互联网邮件扩展类型)百科 MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型.是设定某种扩展名的文件用 ...
- 转:MySQL InnoDB Add Index实现调研
MySQL InnoDB Add Index实现调研 MySQL Add Index实现 MySQL各版本,对于add Index的处理方式是不同的,主要有三种: Copy Table方式 这是Inn ...
- HTTP请求常见错误大全
常见的Http请求错误提示 1xx - 信息提示这些状态代码表示临时的响应.客户端在收到常规响应之前,应准备接收一个或多个 1xx 响应.100 - 继续101 - 切换协议 2xx - 成功这类状态 ...
- &(((struct A*)NULL)->m_float)---offsetof
问题描述: struct A { int m_int; float m_float; }; int main(void) { printf("%p",&(((struct ...
- Git学习笔记(一)Git初识及基本操作
详细完整教程:官方文档,廖神Git教程,武sir 一.什么是Git? 定义:Git是分布式版本控制系统. 1.1什么是版本控制 我们可以回想以下,在我们上学毕业要写论文或是准备一份演讲稿的时候,都会用 ...
- QTP11使用DOM XPath以及CSS识别元素对象
我们知道,像DOM,Html,CSS,XPath等对对象的识别策略广泛运用于一些开源的工具,例如:Selenium,Watir,Watir-Webdriver,以前qtp版本是不支持这些东西的,现在q ...
- leetcode479
public class Solution { public int LargestPalindrome(int n) { ) ; , n) - ; ; v > max / ; v--) { S ...
- Android添加Menu菜单
在安卓中添加Menu菜单十分简单. 步骤: 1.在menu文件夹中的main.xml文件中添加要添加的项目. <menu xmlns:android="http://schemas.a ...