hdu2328(后缀数组 + 二分)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2328
题意: 求 n 个串的字典序最小的最长公共子串
思路: 本题中单个字符串长度不超过 200, 可以暴力枚举一个字符串的所有前缀, 然后用kmp去匹配其他字符串.
我这里是用后缀数组写的. 类似 http://www.cnblogs.com/geloutingyu/p/7450580.html
不过本题是有 n 个字符串, 不能直接暴力判断. 不难想到这里可以直接二分答案长度, 不过 check 函数比较难想到, 具体看代码
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#define rank Rank
using namespace std; const int MAXN = 1e6 + ;
int sol;
char str[MAXN];
int SA[MAXN], rank[MAXN], height[MAXN], sum[MAXN], tp[MAXN], vis[MAXN], tag[(int)(4e3 + )]; bool cmp(int *f, int x, int y, int w){
return f[x] == f[y] && f[x + w] == f[y + w];
} void DA(char *s, int n, int m){
for(int i = ; i < m; i++) sum[i] = ;
for(int i = ; i < n; i++) sum[rank[i] = s[i]]++;
for(int i = ; i < m; i++) sum[i] += sum[i - ];
for(int i = n - ; i >= ; i--) SA[--sum[rank[i]]] = i;
for(int len = ; len <= n; len <<= ){
int p = ;
for(int i = n - len; i < n; i++) tp[p++] = i;
for(int i = ; i < n; i++){
if(SA[i] >= len) tp[p++] = SA[i] - len;
}
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];
swap(rank, tp);
p = ;
rank[SA[]] = ;
for(int i = ; i < n; i++){
rank[SA[i]] = cmp(tp, SA[i - ], SA[i], len) ? p - : p++;
}
if(p >= n) break;
m = p;
}
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;
}
} bool check(int mid, int n, int len){
int cnt = ;
memset(tag, , sizeof(tag));
tag[vis[SA[]]] = ;
for(int i = ; i <= len; i++){
if(height[i] >= mid){
if(!tag[vis[SA[i]]]){
cnt++;
tag[vis[SA[i]]] = ;
if(cnt >= n){
sol = SA[i];
return true;
}
}
}else{
cnt = ;
memset(tag, , sizeof(tag));
tag[vis[SA[i]]] = ;
}
}
return false;
} int main(void){
int n;
while(~scanf("%d", &n) && n){
memset(vis, , sizeof(vis));
scanf("%s", str);
int len = strlen(str);
int mx = len;
for(int i = ; i < n; i++){
vis[len] = ;
str[len] = '';
scanf("%s", str + + len);
mx = max(mx, (int)(strlen(str) - len));
len = strlen(str);
}
str[len] = ;
DA(str, len + , 'z' + );
for(int i = ; i <= len; i++) vis[i] += vis[i - ];
int l = , r = mx;
while(l <= r){
int mid = (l + r) >> ;
if(check(mid, n, len)) l = mid + ;
else r = mid - ;
}
if(l - <= ){
puts("IDENTITY LOST");
continue;
}
for(int i = sol, j = ; j <= l - ; i++, j++){
printf("%c", str[i]);
}
puts("");
}
return ;
}
hdu2328(后缀数组 + 二分)的更多相关文章
- BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )
二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) -------------------------------------------------- ...
- BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案
BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单 ...
- 【bzoj4310】跳蚤 后缀数组+二分
题目描述 很久很久以前,森林里住着一群跳蚤.一天,跳蚤国王得到了一个神秘的字符串,它想进行研究. 首先,他会把串分成不超过 k 个子串,然后对于每个子串 S,他会从S的所有子串中选择字典序最大的那一个 ...
- BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)
题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...
- POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)
洛谷P2743传送门 题目大意:给你一个序列,求其中最长的一对相似等长子串 一对合法的相似子串被定义为: 1.任意一个子串长度都大于等于5 2.不能有重叠部分 3.其中一个子串可以在全部+/-某个值后 ...
- Poj 1743 Musical Theme(后缀数组+二分答案)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...
- Poj 3261 Milk Patterns(后缀数组+二分答案)
Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...
- HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given ...
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)
[题目链接] http://www.spoj.pl/problems/PHRASES/ [题目大意] 求在每个字符串中出现至少两次的最长的子串 [题解] 注意到这么几个关键点:最长,至少两次,每个字符 ...
随机推荐
- HDOJ4768(二分区间)
Flyer Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- [机器学习基础]矩阵基础和numpy
矩阵定义:[摘自百度百科] 由 m × n 个数aij排成的m行n列的数表称为m行n列的矩阵,简称m × n矩阵.记作: 这m×n 个数称为矩阵A的元素,简称为元,数aij位于矩阵A的第i行第j列,称 ...
- navicat for mysql ,mysql版本是8.0的版本,连接数据库报错1251,解决办法。
我的mysql版本是8.0的版本,因为毕竟新的mysql采用新的保密方式,所以就的似乎不能用,改密码方式: 用管理员身份打开cmd mysql -uroot -p(输入密码) 进 ...
- CDM中遍历域及其约束条件、取值范围、引用它的项目
Option ExplicitValidationMode = TrueInteractiveMode = im_BatchDim mdl '当前model'获取当前活动mod ...
- 12-01Js对象##正则表达式##
正则表达式:是一个字符一个字符的验证,通过量词验证字符串: 1.什么是RegExp?RegExp是正则表达式的缩写.RegExp 对象用于规定在文本中检索的内容. 2.定义RegExp:var +变量 ...
- Yahoo浮沉录
Yahoo这一路曾经出过很多好技术 然而,任何人如果只是把 Yahoo 当作一家缺乏聚焦的企业来看也许忽视了公司内部的那些创新—偶尔甚至还有一些很好的产品创意.就拿搜索来说吧,我们说的不是付费搜索,而 ...
- 理解和正确使用Java中的断言(assert)
一.语法形式: Java2在1.4中新增了一个关键字:assert.在程序开发过程中使用它创建一个断言(assertion),它的语法形式有如下所示的两种形式:1.assert conditio ...
- java中的面向对象的三大基本特征
转载,原文来自http://blog.sina.com.cn/s/blog_5f79a56a0100c6ig.html 众所周知,java中的面向对象的三大基本特征是:[封装].[继承].[多态] 一 ...
- 文科妹学 GitHub 简易教程(转)
文科妹学 GitHub 简易教程 #什么是 Github ?必须要放这张图了!!! Git 是由 Linux 之父 Linus Tovalds 为了更好地管理linux内核开发而创立的分布式版 ...
- ReactNative安装配置
1.安装jdk1.8,配置好path, javac,java -version 2.安装设置Android sdk a. 解压:D:\www\sdk\adt-bundle-windows-x86_64 ...