poj 3518 Corporate Identity 后缀数组->多字符串最长相同连续子串
题意:输入N(2 <= N <= 4000)个长度不超过200的字符串,输出字典序最小的最长公共连续子串;
思路:将所有的字符串中间加上分隔符,注:分隔符只需要和输入的字符不同,且各自不同即可,没有必要是最小的字符;
连接后缀数组求解出height之后二分长度,由于height是根据sa数组建立的,所以前面符合的就是字典序最小的,直接找到就停止即可;
ps: 把之前的模板简化了下,A题才是关键;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<stdlib.h>
#include<time.h>
using namespace std;
#define MS0(a) memset(a,0,sizeof(a))
typedef long long ll;
const int MAXN = ;
int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],wv[MAXN];
int cmp(int *r, int a, int b, int l){
return r[a] == r[b] && r[a+l] == r[b+l];
}
void build_sa(int *r, int n, int m){ // 倍增算法 r为待匹配数组 n为总长度 m为字符范围
int i, j, p, *x = t, *y = t2;
for(i = ; i < m; i ++) c[i] = ;
for(i = ; i < n; i ++) c[x[i] = r[i]] ++;
for(i = ; i < m; i ++) c[i] += c[i-];
for(i = n-; i >= ; i --) sa[--c[x[i]]] = i;
for(j = , p = ; p < n; j <<= , m = p){
for(p = , i = n-j; i < n; i ++) y[p++] = i;
for(i = ; i < n; i ++) if(sa[i] >= j) y[p++] = sa[i] - j;
for(i = ; i < n; i ++) wv[i] = x[y[i]];
for(i = ; i < m; i ++) c[i] = ;
for(i = ; i < n; i ++) c[wv[i]] ++;
for(i = ; i < m; i ++) c[i] += c[i-];
for(i = n-; i >= ; i --) sa[--c[wv[i]]] = y[i];
for(swap(x,y), p = , x[sa[]] = , i = ; i < n; i++){
x[sa[i]] = cmp(y, sa[i-], sa[i], j) ? p - : p++;
}
}
}
int rk[MAXN],height[MAXN];
void getHeight(int *r,int n)
{
for(int i = ;i <= n;i++) rk[sa[i]] = i; // rk[i]:后缀i在sa[]中的下标
for(int i = ,j,k = ; i < n; height[rk[i++]] = k){
for(k? k--: ,j = sa[rk[i] - ];r[i+k] == r[j+k];k++);
}
}
int d[MAXN],num[MAXN],vs[],T,len,tot;
char tt[];
bool check(int L)
{
MS0(vs);
int cnt = ;
for(int i = ;i <= tot;i++){
if(height[i] < L){
MS0(vs);
cnt = ;
continue;
}
if(!vs[d[sa[i]]]){
vs[d[sa[i]]] = ;cnt++;
}
if(!vs[d[sa[i-]]]){
vs[d[sa[i-]]] = ;cnt++;
}
if(cnt == T){ //对于同一个长度,我们只取第一次出现的符合条件的字符串;
for(int j = ; j<L; j++)
tt[j] = num[sa[i]+j];
tt[L] = '\0';
return true;
}
}
return false;
}
char str[];
int main()
{
while(scanf("%d",&T) == && T){
tot = ;
for(int i = ;i <= T;i++){
scanf("%s",str);
len = strlen(str);
for(int j = ;j < len;j++)
num[tot] = str[j],d[tot++] = i;
num[tot] = 'z'+i,d[tot++] = 'z'+i;// '#' + i竟然WA了
}
num[tot] = ;//最后添加一个最小字符;
build_sa(num,tot+,);
getHeight(num,tot);
int ans = ,l = ,r = len,mid,id;
while(l <= r){
mid = l + r >> ;
if(check(mid)){ans = mid,l = mid + ;}
else r = mid - ;
}
if(ans){
printf("%s\n",tt);
}
else puts("IDENTITY LOST");
}
return ;
}
poj 3518 Corporate Identity 后缀数组->多字符串最长相同连续子串的更多相关文章
- POJ3450 Corporate Identity —— 后缀数组 最长公共子序列
题目链接:https://vjudge.net/problem/POJ-3450 Corporate Identity Time Limit: 3000MS Memory Limit: 65536 ...
- [poj3450]Corporate Identity(后缀数组)
题意:多个字符串的最长公共子串. 解题关键:字符串的任何一个子串都是这个字符串的某个后缀的前缀.求A和B的最长公共子串等价于求A的后缀和B的后缀的最长公共前缀的最大值. 后缀数组的经典例题,连接在一起 ...
- POJ2774 Long Long Message —— 后缀数组 两字符串的最长公共子串
题目链接:https://vjudge.net/problem/POJ-2774 Long Long Message Time Limit: 4000MS Memory Limit: 131072 ...
- [poj 1743] Musical Theme 后缀数组 or hash
Musical Theme 题意 给出n个1-88组成的音符,让找出一个最长的连续子序列,满足以下条件: 长度大于5 不重叠的出现两次(这里的出现可以经过变调,即这个序列的每个数字全都加上一个整数x) ...
- 利用后缀数组(suffix array)求最长公共子串(longest common substring)
摘要:本文讨论了最长公共子串的的相关算法的时间复杂度,然后在后缀数组的基础上提出了一个时间复杂度为o(n^2*logn),空间复杂度为o(n)的算法.该算法虽然不及动态规划和后缀树算法的复杂度低,但其 ...
- poj 3294 后缀数组 多字符串中不小于 k 个字符串中的最长子串
Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16223 Accepted: 4763 Descr ...
- 后缀数组(模板题) - 求最长公共子串 - poj 2774 Long Long Message
Language: Default Long Long Message Time Limit: 4000MS Memory Limit: 131072K Total Submissions: 21 ...
- POJ 3450 Corporate Identity(KMP)
[题目链接] http://poj.org/problem?id=3450 [题目大意] 求k个字符串的最长公共子串,如果有多个答案,则输出字典序最小的. [题解] 我们对第一个串的每一个后缀和其余所 ...
- POJ 1226 Substrings(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...
随机推荐
- html/css 两个div在同一行
在界面设计的时候,经常需要将两个div在同一行显示. 但是每次都会忘记怎么做,特此随笔,备忘. 如以下要将“第一个div”和“第二个div”显示在同一行: <div id="id1&q ...
- javaScript入门1--组成,基本使用
javaScript:脚本语言,最初是为了实现在客户端进行的表单验证以减少服务器的数据交互次数,如今可用在页面交互,计算,拥有了闭包,匿名(拉姆达)函数,甚至元编程等特性. javaScript实现的 ...
- iOS之可拖拽重排的CollectionView
修复了拖拽滚动时抖动的一个bug,新增编辑模式,进入编辑模式后不用长按触发手势,且在开启抖动的情况下会自动进入抖动模式,如图: test.gif 图1:垂直滚动 drag1.gif 图2:水平滚动 d ...
- Windows Azure 微软公有云体验(二) 存储成本比较分析
Windows Azure 微软公有云已经登陆中国有一段时间了,现在是处于试用阶段,Windows Azure的使用将会给管理信息系统的开发.运行.维护带来什么样的新体验呢? Windows Azur ...
- asp.net session容易丢失解决方案
web Form 网页是基于HTTP的,它们没有状态, 这意味着它们不知道所有的请求是否来自 同一台客户端计算机,网页是受到了破坏,以及是否得到了刷新,这样就可能造成信息的 丢失. 于是, 状态管理就 ...
- Redis中文显示为Unicode编码的解决办法
通过Xshell远程连接Linux中的Redis数据库.... 存入Reids中的value有中文. Xshell得到之后中文并不显示为乱码,显示的是中文对应的Unicode编码: 在Xshell中字 ...
- js中call和apply的用法和区别
它们的作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数方式有所区别: obj.call(thisObj, arg1, arg2, ...); obj.apply(thisObj, [arg1 ...
- UML学习-总体概念篇
前言:我们在实施一个项目时,前期的设计是非常重要的,如建筑师在建造一个建筑时,需要事先设计图纸,设计图纸是设计的语言,是不同的工程设计人员.设计人员和生产人员之间进行沟通的语言,在一个现代化的工程里面 ...
- JAVA之经典Student问题1
通过“三目运算符”求最大值与最小值. class student { //定义学生编号 private String stu; //学生姓名 private String name; //学生书信成绩 ...
- RNN-theano代码解析
import theano import numpy import os import pdb from theano import tensor as T from collections impo ...