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 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...
随机推荐
- PHP读书笔记(7)- 函数
自定义函数 PHP内置了超过1000个函数,因此函数使得PHP成为一门非常强大的语言.大多数时候我们使用系统的内置函数就可以满足需求,但是自定义函数通过将一组代码封装起来,使代码进行复用,程序结构与逻 ...
- ASP.NET MVC 4 如何避免数据库被自动创建或自动迁移
保哥说要想避免数据库被自动创建或自动迁移,可以在Global.asax文件里的Application_Start方法中加入: System.Data.Entity.Database.SetInitia ...
- 【转载】Android使用Application总结
Application 配置全局Context 第一步.写一个全局的单例模式的MyApplication继承自Application 覆盖onCreate ,在这个方法里面实例化Application ...
- Linux下的权限掩码umask
权限掩码umask 我们都知道在linux下创建一个文件或者目录之后是可以通过chmod等命令进行权限设置,来达到给当前用户.用户组用户以及其他用户分配不同的访问权限.那么,我们新创建的目录和文件本身 ...
- 【Stirling Number】
两类Stirling Number的简介与区别(参考自ACdreamer的CSDN) Stirling Number I --- s(n,k):将n个物体排成k个非空循环排列(环)的方法数. 递推式: ...
- Git工作流
关于git工作原理请参见:http://blog.csdn.net/zdy0_2004/article/details/46552227
- poj 2823 单调队列
思路:裸的单调队列. #include<iostream> #include<cstring> #include<cstdio> #include<algor ...
- sqlserver 关于快照
数据库快照:是数据库某一时间点的视图,快照涉及最初目的是为了报表服务,快照还可以和镜像结合来达到读写分离的目的 数据库快照:是sqlserver数据库的只读静态视图快照的作用:1 提供了一个静态的视图 ...
- C# winform 选择项 省市连动
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- 设置win7任务栏显示标题,而不显示缩略图
win7系统的任务栏可以显示桌面缩略图,这是非常好的一个功能,但是有时候我们希望只显示标题,如下所示 怎样设置呢?只要在桌面上的计算机图标上面“右键”,选择“属性”,在弹出的窗口选择“高级系统设置”, ...