[poj3450]Corporate Identity(后缀数组)
题意:多个字符串的最长公共子串。
解题关键:字符串的任何一个子串都是这个字符串的某个后缀的前缀。求A和B的最长公共子串等价于求A的后缀和B的后缀的最长公共前缀的最大值。
后缀数组的经典例题,连接在一起,二分长度,height数组遍历即可。
注意flag的问题,采用二分小于的方式,可能会出现有最优解但是flag为false的情况,下界需要-1,采用0,而采用等于的话,就不会出现,不过有些题会出现死循环。
还有因为多添加的符号一定不会加入vis数组,所以vis数组只需建立4000即可。
为什么两个字符串不需要二分?而多个字符串需要二分?因为 两个字符串可以直接判定height[i]是属于两个字符串的最大公共子串,而多个必须通过vis数组判定。
法一:
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int N=;
int r[N],id[N];
char tmp[],ans[];
bool vis[]; int wa[N],wb[N],wv[N],wc[N],n,m;
bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
void make_sa(int *r,int *sa,int n,int m){
int i,j,p,*x=wa,*y=wb;
for(i=;i<m;i++) wc[i]=;
for(i=;i<n;i++) wc[x[i]=r[i]]++;
for(i=;i<m;i++) wc[i]+=wc[i-];
for(i=n-;i>=;i--) sa[--wc[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++) wc[i]=;
for(i=;i<n;i++) wc[wv[i]]++;
for(i=;i<m;i++) wc[i]+=wc[i-];
for(i=n-;i>=;i--) sa[--wc[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++;
}
return;
}
int rank1[N],height[N],sa[N];
void make_height(int *r,int *sa,int n){
int i,j,k=;
for(i=;i<=n;i++) rank1[sa[i]]=i;
for(i=;i<n;height[rank1[i++]]=k)
for(k?k--:,j=sa[rank1[i]-];r[i+k]==r[j+k];k++);
return;
} bool check(int x){
memset(vis,,sizeof vis);
int cnt=;
for(int i=;i<=n;i++){
if(height[i]<x){
memset(vis,,sizeof vis);
cnt=;
continue;
}
if(!vis[id[sa[i-]]]) vis[id[sa[i-]]]=true,cnt++;
if(!vis[id[sa[i]]]) vis[id[sa[i]]]=true,cnt++;
if(cnt==m){
for(int j=;j<x;j++) ans[j]=r[sa[i]+j]+'a'-;ans[x]=;
return true;
}
}
return false;
} bool erfen(int l,int r){
bool flag=false;
while(l<r){
int mid=(l+r+)>>;
if(check(mid)) l=mid,flag=true;
else r=mid-;
}
return flag;
} int main() {
while(scanf("%d",&m)&&m){
n=;
int temp=;
for(int i=;i<=m;i++){
scanf("%s",tmp);
int siz=strlen(tmp);
for(int j=;j<siz;j++) id[n]=i,r[n++]=tmp[j]-'a'+;
id[n]=temp;
r[n++]=temp++;
}
r[n]=;
make_sa(r,sa,n+,);
make_height(r,sa,n);
bool f=erfen(,);//为什么0可以,1不可以
if(f) printf("%s\n",ans);
else printf("IDENTITY LOST\n");
}
}
法二:
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int N=;
int r[N],id[N];
char tmp[],ans[];
bool vis[]; int wa[N],wb[N],wv[N],wc[N],n,m;
bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
void make_sa(int *r,int *sa,int n,int m){
int i,j,p,*x=wa,*y=wb;
for(i=;i<m;i++) wc[i]=;
for(i=;i<n;i++) wc[x[i]=r[i]]++;
for(i=;i<m;i++) wc[i]+=wc[i-];
for(i=n-;i>=;i--) sa[--wc[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++) wc[i]=;
for(i=;i<n;i++) wc[wv[i]]++;
for(i=;i<m;i++) wc[i]+=wc[i-];
for(i=n-;i>=;i--) sa[--wc[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++;
}
return;
}
int rank1[N],height[N],sa[N];
void make_height(int *r,int *sa,int n){
int i,j,k=;
for(i=;i<=n;i++) rank1[sa[i]]=i;
for(i=;i<n;height[rank1[i++]]=k)
for(k?k--:,j=sa[rank1[i]-];r[i+k]==r[j+k];k++);
return;
} bool check(int x){
memset(vis,,sizeof vis);
int cnt=;
for(int i=;i<=n;i++){
if(height[i]<x){
memset(vis,,sizeof vis);
cnt=;
continue;
}
if(!vis[id[sa[i-]]]) vis[id[sa[i-]]]=true,cnt++;
if(!vis[id[sa[i]]]) vis[id[sa[i]]]=true,cnt++;
if(cnt==m){
for(int j=;j<x;j++) ans[j]=r[sa[i]+j]+'a'-;ans[x]=;
return true;
}
}
return false;
} bool erfen(int l,int r){
bool flag=false;
while(l<=r){
int mid=(l+r+)>>;
if(check(mid)) l=mid+,flag=true;
else r=mid-;
}
return flag;
} int main() {
while(scanf("%d",&m)&&m){
n=;
int temp=;
for(int i=;i<=m;i++){
scanf("%s",tmp);
int siz=strlen(tmp);
for(int j=;j<siz;j++) id[n]=i,r[n++]=tmp[j]-'a'+;
id[n]=temp;
r[n++]=temp++;
}
r[n]=;
make_sa(r,sa,n+,);
make_height(r,sa,n);
bool f=erfen(,);//为什么0可以,1不可以
if(f) printf("%s\n",ans);
else printf("IDENTITY LOST\n");
}
}
dc3:依然注意是3倍的问题
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int N=;
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[N],wb[N],wv[N],ws1[N];
int c0(int *r,int a,int b){ return r[a]==r[b]&&r[a+]==r[b+]&&r[a+]==r[b+]; }
int c12(int k,int *r,int a,int b){
if(k==) return r[a]<r[b]||r[a]==r[b]&&c12(,r,a+,b+);
else return r[a]<r[b]||r[a]==r[b]&&wv[a+]<wv[b+];
}
void sort(int *r,int *a,int *b,int n,int m){
int i;
for(i=;i<n;i++) wv[i]=r[a[i]];
for(i=;i<m;i++) ws1[i]=;
for(i=;i<n;i++) ws1[wv[i]]++;
for(i=;i<m;i++) ws1[i]+=ws1[i-];
for(i=n-;i>=;i--) b[--ws1[wv[i]]]=a[i];
return;
}
void dc3(int *r,int *sa,int n,int m){
int i,j,*rn=r+n,*san=sa+n,ta=,tb=(n+)/,tbc=,p;
r[n]=r[n+]=;
for(i=;i<n;i++) if(i%!=) wa[tbc++]=i;
sort(r+,wa,wb,tbc,m);
sort(r+,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p=,rn[F(wb[])]=,i=;i<tbc;i++)
rn[F(wb[i])]=c0(r,wb[i-],wb[i])?p-:p++;
if(p<tbc) dc3(rn,san,tbc,p);
else for(i=;i<tbc;i++) san[rn[i]]=i;
for(i=;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*;
if(n%==) wb[ta++]=n-;
sort(r,wb,wa,ta,m);
for(i=;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
for(i=,j=,p=;i<ta && j<tbc;p++)
sa[p]=c12(wb[j]%,r,wa[i],wb[j])?wa[i++]:wb[j++];
for(;i<ta;p++) sa[p]=wa[i++];
for(;j<tbc;p++) sa[p]=wb[j++];
return;
}
int rank1[N],height[N],sa[*N];
void make_height(int *r,int *sa,int n){
int i,j,k=;
for(i=;i<=n;i++) rank1[sa[i]]=i;
for(i=;i<n;height[rank1[i++]]=k)
for(k?k--:,j=sa[rank1[i]-];r[i+k]==r[j+k];k++);
return;
}
int r[*N],id[N],n,m;
char tmp[],ans[];
bool vis[]; bool check(int x){
memset(vis,,sizeof vis);
int cnt=;
for(int i=;i<=n;i++){
if(height[i]<x){
memset(vis,,sizeof vis);
cnt=;
continue;
}
if(!vis[id[sa[i-]]]) vis[id[sa[i-]]]=true,cnt++;
if(!vis[id[sa[i]]]) vis[id[sa[i]]]=true,cnt++;
if(cnt==m){
for(int j=;j<x;j++) ans[j]=r[sa[i]+j]+'a'-;ans[x]=;
return true;
}
}
return false;
} bool erfen(int l,int r){
bool flag=false;
while(l<r){
int mid=(l+r+)>>;
if(check(mid)) l=mid,flag=true;
else r=mid-;
}
return flag;
} int main() {
while(scanf("%d",&m)&&m){
n=;
int temp=;
for(int i=;i<=m;i++){
scanf("%s",tmp);
int siz=strlen(tmp);
for(int j=;j<siz;j++) id[n]=i,r[n++]=tmp[j]-'a'+;
id[n]=temp;
r[n++]=temp++;
}
r[n]=;
dc3(r,sa,n+,);
make_height(r,sa,n);
bool f=erfen(,);//为什么0可以,1不可以
if(f) printf("%s\n",ans);
else printf("IDENTITY LOST\n");
}
}
[poj3450]Corporate Identity(后缀数组)的更多相关文章
- POJ3450 Corporate Identity —— 后缀数组 最长公共子序列
题目链接:https://vjudge.net/problem/POJ-3450 Corporate Identity Time Limit: 3000MS Memory Limit: 65536 ...
- poj 3518 Corporate Identity 后缀数组->多字符串最长相同连续子串
题目链接 题意:输入N(2 <= N <= 4000)个长度不超过200的字符串,输出字典序最小的最长公共连续子串; 思路:将所有的字符串中间加上分隔符,注:分隔符只需要和输入的字符不同, ...
- POJ-3450 Corporate Identity (KMP+后缀数组)
Description Beside other services, ACM helps companies to clearly state their “corporate identity”, ...
- POJ3450 Corporate Identity 【后缀数组】
Corporate Identity Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 7662 Accepted: 264 ...
- POJ3450 Corporate Identity
后缀数组. 解决多个字符串的最长公共子串. 采用对长度的二分,将子串按height分组,每次判断是否在每个字符串中都出现过. 复杂度O(NlogN) By:大奕哥 #include<cstrin ...
- [HDU2328]Corporate Identity(后缀数组)
传送门 求 n 个串的字典序最小的最长公共子串. 和 2 个串的处理方法差不多. 把 n 个串拼接在一起,中间连上一个没有出现过的字符防止匹配过界. 求出 height 数组后二分公共子串长度给后缀数 ...
- POJ3080 POJ3450Corporate Identity(广义后缀自动机||后缀数组||KMP)
Beside other services, ACM helps companies to clearly state their “corporate identity”, which includ ...
- hdu2328 Corporate Identity【string库使用】【暴力】【KMP】
Corporate Identity Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- kuangbin带你飞 后缀数组 题解
2份模板 DC3 . 空间复杂度O3N 时间复杂度On #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb)) #define G(x) ((x) < ...
随机推荐
- 关于 Swift 的一点初步看法
本文转自:http://onevcat.com/2014/06/my-opinion-about-swift/ 感谢原作者 尽管四点半就起床去排队等入场,结果还是仅仅能坐在了蛮后面的位置看着大屏幕參加 ...
- VS2017快捷键
1.回到上一个光标位置/前进到下一个光标位置 (1)回到上一个光标位置:使用组合键“Ctrl + -”; (2)前进到下一个光标位置:“Ctrl + Shift + - ”. 2.复制/剪切/删除整行 ...
- 用变量a给出下面的定义。[中国台湾某著名CPU生产公司2005年面试题]
(1)一个整型数(An integer)(2)一个指向整型数的指针(A pointer to an integer)(3)一个指向指针的指针,它指向的指针是指向一个整型数(A pointer to a ...
- 【BZOJ1146】[CTSC2008]网络管理Network 树状数组+DFS序+主席树
[BZOJ1146][CTSC2008]网络管理Network Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工 ...
- Kubernetes TensorFlow 默认 特定 集群管理器
Our goal is to foster an ecosystem of components and tools that relieve the burden of running applic ...
- pjax + tp5,实现局部无刷新返回数据
文件1:\application\admin\controller\Setting.php 最后一句代码:要fetch原页面 <?php namespace app\admin\controll ...
- 我的Android进阶之旅------>报 error: Apostrophe not preceded by \ 的错误解决办法
今天对项目进行国际化翻译的时候控制台出现了以下的错误: res/values/strings.xml:100: error: Apostrophe not preceded by \ (in Sorr ...
- ios之编码规范具体说明
iOS代码规范: 所有代码规范所有遵循苹果sdk的原则,不清楚的请訪问苹果SDK文档或下载官方Demo查看. 1.project部分: 将项目中每一个功能模块相应的源文件放入同一目录下,使用虚拟目录. ...
- python环境的caffe配置
基本按照这个教程来 http://blog.csdn.net/zb1165048017/article/details/52980102 步骤 安装Anaconda2,去官网上下载,注意下载对应自己p ...
- react服务端渲染
一.服务端渲染的好处 1.SEO, 让搜索引擎更容易读取页面内容: 2.首屏渲染速度更快(重点),无需等待JS文件下载执行过程: 3.更易于维护,服务端和客户端可以共享某些代码: 二.实现原理 服务端 ...