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/ [题目大意] 求在每个字符串中出现至少两次的最长的子串 [题解] 注意到这么几个关键点:最长,至少两次,每个字符 ...
随机推荐
- 关于C#客户端引用C++ dll的问题
近期在做项目的过程中需要在Winform客户端项目引用由C++编译的DLL,于是对相关的内容进行了一些研究,有几点心得总结如下. 第一步是制作要引用的类库: (1)首先拿到C++的dll,需要注意的是 ...
- JavaScript 中对小数取整的常用函数
常见的js截取小数的方法 1.丢弃小数部分,保留整数部分 js:parseInt(7/2) 2.向上取整,有小数就整数部分加1 js: Math.ceil(7/2) 3,四舍五入. js: Math. ...
- 开发环境入门 linux基础 (部分) 复制 用户和组操作 权限更改
复制 用户和组操作 权限更改 CP 复制命令 cp 源文件 目标文件 a) –r(recursive,递归的):递归地复制目录.当复制一个目录时,复制该目录中所有的内容,其中包括子目录的全部内容. b ...
- linux命令-mke2fs
想在磁盘下写东西,必须要先格式化 /////////////////////////////////////////////////////////////////////////////////// ...
- x264中重要结构体参数解释,参数设置,函数说明 <转>
x264中重要结构体参数解释http://www.usr.cc/thread-51995-1-3.htmlx264参数设置http://www.usr.cc/thread-51996-1-3.html ...
- DAY11-MYSQL视图、触发器、事务、存储过程、函数
一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可以将该结果集当做表来使用. 使用视图我们可以把查询过程中的 ...
- DAY10-MYSQL完整性约束
一 介绍 约束条件与数据类型的宽度一样,都是可选参数 作用:用于保证数据的完整性和一致性主要分为: PRIMARY KEY (PK) 标识该字段为该表的主键,可以唯一的标识记录 FOREIGN KEY ...
- eclipse中maven的配置与使用
以eclipse Juno版本为例 1.插件安装 eclipse==>help====>install new software===>add name :m2e location: ...
- Android ScrollView 内部控件 layout_margin失效的解决方法
在<ScrollView> 的<LinearLayout >属性里面加入android:layout_gravity="top" <LinearLa ...
- android手机分辨率的一些说明
Android上常见度量单位 px(像素):屏幕上的点,绝对长度,与硬件相关 in(英寸):长度单位 mm(毫米):长度单位 pt(磅):1/72英寸,point dp(与密度无关的像素):一种基于屏 ...