【题意】

  多串求LCS。

 
【思路】
 
  主要是想找一下SAM的优越感 :) velui good
  后缀数组划分height需要注意不少细节 <_<,然后不停debug
 
 
【代码】
 
 #include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; const int N = *+; char s[N],tmp[N];
int sa[N],c[N],t[N],t2[N],rank[N],height[N]; void build_sa(int m,int n) {
int i,k,*x=t,*y=t2;
for(i=;i<m;i++) c[i]=;
for(i=;i<n;i++) c[x[i]=s[i]]++;
for(i=;i<m;i++) c[i]+=c[i-];
for(i=n-;i>=;i--) sa[--c[x[i]]]=i;
for(k=;k<=n;k<<=) {
int p=;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=;i<m;i++) c[i]=;
for(i=;i<n;i++) c[x[y[i]]]++;
for(i=;i<m;i++) c[i]+=c[i-];
for(i=n-;i>=;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=; x[sa[]]=;
for(i=;i<n;i++)
x[sa[i]]=y[sa[i]]==y[sa[i-]]&&y[sa[i]+k]==y[sa[i-]+k]? p-:p++;
if(p>=n) break;
m=p;
}
}
void get_height(int n) {
int i,j,k=;
for(int i=;i<=n;i++) rank[sa[i]]=i;
for(int i=;i<n;i++) {
if(k) k--;
j=sa[rank[i]-];
while(s[j+k]==s[i+k]) k++;
height[rank[i]]=k;
}
} int flag[],cr[N];
bool can(int M,int n,int k) {
int kase=,cnt=;
flag[cr[sa[]]]=kase;
for(int i=;i<n;i++)
if(height[i]<M)
cnt=,flag[cr[sa[i]]]=++kase;
else {
int r=cr[sa[i]];
if(flag[r]!=kase) cnt++,flag[r]=kase;
if(cnt==k) return true;
}
return false;
} int main() {
int n; scanf("%d",&n);
int block=n,sz=;
for(int i=;i<n;i++) {
scanf("%s",tmp);
for(int j=;tmp[j];j++)
s[sz]=tmp[j],cr[sz++]=i;
s[sz]=--block,cr[sz++]=i;
} build_sa('z'+,sz);
get_height(sz); int L=,R=sz;
while(L<R) {
int M=L+(R-L+)/;
if(can(M,sz,n)) L=M;
else R=M-;
}
printf("%d",L);
return ;
}

SA

 #include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; const int N = *+; char s[N];
int last,sz,fa[N],ch[N][],l[N],mn[N],mx[N];
int c[N],b[N]; void add(int x) {
int c=s[x]-'a';
int p=last,np=++sz; last=np;
mn[np]=l[np]=x+;
for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=;
else {
int q=ch[p][c];
if(l[p]+==l[q]) fa[np]=q;
else {
int nq=++sz; mn[nq]=l[nq]=l[p]+;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
for(;q==ch[p][c];p=fa[p]) ch[p][c]=nq;
}
}
} int main() {
int n; scanf("%d",&n);
last=++sz;
scanf("%s",s);
for(int i=;s[i];i++) add(i);
for(int i=;i<=sz;i++) c[l[i]]++;
for(int i=;i<=strlen(s);i++) c[i]+=c[i-];
for(int i=;i<=sz;i++) b[c[l[i]]--]=i;
int ans=;
for(int i=;i<n;i++) {
scanf("%s",s);
int p=,len=;
for(int i=;s[i];i++) {
int c=s[i]-'a';
if(ch[p][c]) { len++; p=ch[p][c]; }
else {
while(p&&!ch[p][c]) p=fa[p];
if(!p) { len=; p=; }
else { len=l[p]+; p=ch[p][c]; }
}
mx[p]=max(mx[p],len);
}
for(int i=sz;i;i--) {
int p=b[i];
mn[p]=min(mn[p],mx[p]);
if(fa[p]) mx[fa[p]]=max(mx[fa[p]],mx[p]);
mx[p]=;
}
}
for(int i=;i<=sz;i++)
if(ans<mn[i]) ans=mn[i];
printf("%d",ans);
return ;
}

SAM

 

bzoj2946 [Poi2000]公共串(SA,SAM)的更多相关文章

  1. 【BZOJ 2946】 2946: [Poi2000]公共串 (SAM)

    2946: [Poi2000]公共串 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1063  Solved: 469 Description      ...

  2. [BZOJ2946] [Poi2000]公共串解题报告|后缀数组

    给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 单词个数<=5,每个单词长度<=2000     尽管最近在学的是SAM...但是看到这个题还是忍不住想写SA... (其实是不 ...

  3. [bzoj2946][Poi2000]公共串_后缀数组_二分

    公共串 bzoj-2946 Poi-2000 题目大意:给定$n$个字符串,求他们的最长公共子串. 注释:$1\le n\le 5$,$1\le minlen<maxlen\le 2000$. ...

  4. bzoj 2946: [Poi2000]公共串【SAM】

    对第一个串建SAM,把剩下的串在上面跑,每次跑一个串的时候在SAM的端点上记录匹配到这的最大长度,然后对这些串跑的结果取min,然后从这些节点的min中取max就是答案 注意在一个点更新后它的祖先也会 ...

  5. SPOJ1812: LCS2 - Longest Common Substring II & BZOJ2946: [Poi2000]公共串

    [传送门:SPOJ1811&BZOJ2946] 简要题意: 给出若干个字符串,求出这些字符串的最长公共子串 题解: 后缀自动机 这两道题的区别只是在于一道给出了字符串个数,一个没给,不过也差不 ...

  6. [BZOJ2946][Poi2000]公共串解题报告|后缀自动机

    鉴于SAM要简洁一些...于是又写了一遍这题... 不过很好呢又学到了一些新的东西... 这里是用SA做这道题的方法 首先还是和两个字符串的一样,为第一个字符串建SAM 然后每一个字符串再在这个SAM ...

  7. BZOJ2946 [Poi2000]公共串(后缀自动机)

    Description          给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l        读入单词 l        计算最长公共子串的长度 l        输 ...

  8. BZOJ2946 Poi2000 公共串 【后缀自动机】

    Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单词 l 计算最长公共子串的长度 l 输出结果 Input 文件的第一行是整数 n,1<=n& ...

  9. bzoj2946: [Poi2000]公共串

    SAM处女题qwq #include <iostream> #include <cstdio> #include <cstring> #include <cm ...

随机推荐

  1. sql server触发器的例子

    发布:thebaby   来源:脚本学堂     [大 中 小] 本文介绍下,在sql server数据库中使用触发器的简单例子,有需要的朋友可以参考下,希望对你有一定的帮助. 原文地址:http:/ ...

  2. ecshop用户中心订单详情增加快递单物流信息查询显示的功能

    1,themes\default\user_transaction.dwt 找到: <!--{if $action eq order_detail} --> 在下面一行加入: <st ...

  3. slqplus 帮助手册

    1.查看sqlplus的帮助是否可用,必须登录了才可用. D:\app\product\\db_1\sqlplus\admin\help>sqlplus /nolog SQL :: Copyri ...

  4. Python SqlAlchemy使用方法

    1.初始化连接 from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker engine = create ...

  5. hadoop2.2.0+hive-0.10.0完全分布式安装方法

    hadoop+hive-0.10.0完全分布式安装方法 1.jdk版本:jdk-7u60-linux-x64.tar.gz http://www.oracle.com/technetwork/cn/j ...

  6. Linux和Windows下查看环境变量方法对比

    摘自:Linux和Windows下查看环境变量方法对比 一.查看所有环境变量的名称和值 Linux下:export Windows下:set 二.根据名称查该环境变量的值 Linux下:echo $环 ...

  7. 带节假日JS万年历控件代码

    <form name="CLD" class="content"> <table width="100%" border= ...

  8. How Does #DeepDream Work?

    How Does #DeepDream Work? Do neural networks hallucinate of electronic dogs? If you’ve been browsing ...

  9. javaweb学习总结(三十七)——获得MySQL数据库自动生成的主键

    测试脚本如下: 1 create table test1 2 ( 3 id int primary key auto_increment, 4 name varchar(20) 5 ); 测试代码: ...

  10. ArcGis 在线地图相关资源

    原文:ArcGis 在线地图相关资源 世界边界和地点:http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Bou ...