bzoj2946 [Poi2000]公共串(SA,SAM)
【题意】
多串求LCS。
#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)的更多相关文章
- 【BZOJ 2946】 2946: [Poi2000]公共串 (SAM)
2946: [Poi2000]公共串 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 1063 Solved: 469 Description ...
- [BZOJ2946] [Poi2000]公共串解题报告|后缀数组
给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 单词个数<=5,每个单词长度<=2000 尽管最近在学的是SAM...但是看到这个题还是忍不住想写SA... (其实是不 ...
- [bzoj2946][Poi2000]公共串_后缀数组_二分
公共串 bzoj-2946 Poi-2000 题目大意:给定$n$个字符串,求他们的最长公共子串. 注释:$1\le n\le 5$,$1\le minlen<maxlen\le 2000$. ...
- bzoj 2946: [Poi2000]公共串【SAM】
对第一个串建SAM,把剩下的串在上面跑,每次跑一个串的时候在SAM的端点上记录匹配到这的最大长度,然后对这些串跑的结果取min,然后从这些节点的min中取max就是答案 注意在一个点更新后它的祖先也会 ...
- SPOJ1812: LCS2 - Longest Common Substring II & BZOJ2946: [Poi2000]公共串
[传送门:SPOJ1811&BZOJ2946] 简要题意: 给出若干个字符串,求出这些字符串的最长公共子串 题解: 后缀自动机 这两道题的区别只是在于一道给出了字符串个数,一个没给,不过也差不 ...
- [BZOJ2946][Poi2000]公共串解题报告|后缀自动机
鉴于SAM要简洁一些...于是又写了一遍这题... 不过很好呢又学到了一些新的东西... 这里是用SA做这道题的方法 首先还是和两个字符串的一样,为第一个字符串建SAM 然后每一个字符串再在这个SAM ...
- BZOJ2946 [Poi2000]公共串(后缀自动机)
Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单词 l 计算最长公共子串的长度 l 输 ...
- BZOJ2946 Poi2000 公共串 【后缀自动机】
Description 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l 读入单词 l 计算最长公共子串的长度 l 输出结果 Input 文件的第一行是整数 n,1<=n& ...
- bzoj2946: [Poi2000]公共串
SAM处女题qwq #include <iostream> #include <cstdio> #include <cstring> #include <cm ...
随机推荐
- mysql更改数据文件目录及my.ini位置| MySQL命令详解
需求:更改mysql数据数据文件目录及my.ini位置. 步骤: 1.查找my.ini位置,可通过windows服务所对应mysql启动项,查看其对应属性->可执行文件路径,获取my.ini路径 ...
- platform平台设备驱动简化示例代码
driver.c: #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h& ...
- Linux下简易蜂鸣器驱动代码及测试实例
驱动代码: #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> ...
- IDEA的使用
1.设置字体file->setting->color$fonts->font 保存提示设置file->Settings -> Editor -> General - ...
- 使用自定义 URL 实现控制器之间的跳转-b
一个app往往有很多界面,而界面之间的跳转也就是对应控制器的跳转,控制器的跳转一般有两种情况 push 或者 modal,push 和 modal 的默认效果是系统提供的 文章配图 1. 概述 系统提 ...
- spoj LCS
初识后缀自动机: 推荐学习:http://blog.sina.com.cn/s/blog_7812e98601012dfv.html #include<cstdio> #include&l ...
- x86, x86-64, i386, IA32, IA64...
转自x86, x86-64, i386, IA32, IA64... x86:Intel从16位微处理器8086开始的整个CPU芯片系列,系列中的每种型号都保持与以前的各种型号兼容,主要有8086,8 ...
- linux hosts一个诡异问题
最近部署环境时遇到一个古怪问题. 背景环境: tomcat服务器 : 192.168.13.78 简称t 依赖服务器 : 192.168.12.159 简称s 二者关系 :t服务器的tomcat应 ...
- Android进阶篇-内存管理
很多时候我们需要考虑Android平台上的内存管理问题,Dalvik VM给每个进程都分配了一定量的可用堆内存,当我们处理一些耗费资源的操作时可能会产生OOM错误(OutOfMemoryError)这 ...
- 内存不足时Android 系统如何Kill进程
[转]内存不足时Android 系统如何Kill进程 大家其实都或多或少知道,Android系统有自已的任务管理器,当系统内存不足时,系统需要KILL一些进程(应用),以回收一部分资源,来保证系统仍可 ...