后缀数组


  好感动,复习了下后缀数组居然写出来了……(感谢ykz大神)

  求最长公共子串……WA了一发是因为:【不同字符串之间要用不同的特殊字符隔开】否则就会匹配到相同→_→比如都是aaa结尾,如果用相同特殊字符就会使得最长公共子串变成aaa#这样子……

 /**************************************************************
Problem: 2946
User: Tunix
Language: C++
Result: Accepted
Time:60 ms
Memory:4104 kb
****************************************************************/ //BZOJ 2946
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
typedef long long LL;
inline int getint(){
int r=,v=; char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-;
for(; isdigit(ch);ch=getchar()) v=v*+ch-'';
return r*v;
}
const int N=1e5+,INF=~0u>>;
/*******************template********************/
int sa[N],rank[N],height[N],belong[N],wa[N],wb[N],c[N],n,m;
int len[];
char s[N];
bool cmp(int *r,int a,int b,int l){
return r[a]==r[b] && r[a+l]==r[b+l];
}
void DA(char *s,int *sa,int n,int m){
int i,j,p,*x=wa,*y=wb;
rep(i,m) c[i]=;
rep(i,n) c[x[i]=s[i]]++;
F(i,,m-) c[i]+=c[i-];
D(i,n-,) sa[--c[x[i]]]=i;
for(j=,p=;p<n;j<<=,m=p){
for(p=,i=n-j;i<n;i++) y[p++]=i;
rep(i,n) if (sa[i]>=j) y[p++]=sa[i]-j; rep(i,m) c[i]=;
rep(i,n) c[x[y[i]]]++;
F(i,,m-) c[i]+=c[i-];
D(i,n-,) sa[--c[x[y[i]]]]=y[i];
swap(x,y); p=; x[sa[]]=;
F(i,,n-) x[sa[i]]=cmp(y,sa[i-],sa[i],j) ? p- : p++;
}
}
void calheight(char *s,int *sa,int n){
int k=;
F(i,,n) rank[sa[i]]=i;
rep(i,n){
if (k) k--;
int j=sa[rank[i]-];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("2946.in","r",stdin);
freopen("2946.out","w",stdout);
#endif
n=getint();int l=;
F(i,,n){
scanf("%s",s+l);
len[i]=strlen(s)-l;
l=strlen(s);
s[l++]='a'-n+i;
}
rep(i,l) s[i]=s[i]-'a'+;
l--;
DA(s,sa,l+,);
calheight(s,sa,l);
int tmp=;
rep(i,l){
if (s[i]<) {tmp++;continue;}
belong[rank[i]]=tmp;
} bool vis[]={};
int L=,R=,mid,cnt,ans=;
while(L<=R){
mid=(L+R)>>;bool sign=;
cnt=; memset(vis,,sizeof vis);
F(i,n,l){
if (height[i]<mid){
cnt=;memset(vis,,sizeof vis);
vis[belong[i]]=; continue;
}
if (!vis[belong[i]]) vis[belong[i]]=,cnt++;
if (cnt==n) sign=;
}
if (sign) ans=mid,L=mid+;
else R=mid-;
}
printf("%d\n",ans);
return ;
}

2946: [Poi2000]公共串

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 160  Solved: 67
[Submit][Status][Discuss]

Description

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

Input

 
文件的第一行是整数 n,1<=n<=5,表示单词的数量。接下来n行每行一个单词,只由小写字母组成,单词的长度至少为1,最大为2000。
 

Output

仅一行,一个整数,最长公共子串的长度。
 

Sample Input

3
abcb
bca
acbc

Sample Output

HINT

Source

[Submit][Status][Discuss]

【BZOJ】【2946】【POI2000】公共串的更多相关文章

  1. BZOJ 2946: [Poi2000]公共串

    2946: [Poi2000]公共串 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 342[Submit][Status][D ...

  2. BZOJ 2946: [Poi2000]公共串( 后缀自动机 )

    一个串建后缀自动机, 其他串在上面跑, 然后用当前串跑的去更新全部 ------------------------------------------------------------------ ...

  3. bzoj 2946 [Poi2000]公共串——后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2946 对每个串都建一个后缀自动机,然后 dfs 其中一个自动机,记录同步的话在别的自动机上走 ...

  4. BZOJ 2946 [Poi2000]公共串 (二分+Hash/二分+后缀数组/后缀自动机)

    求多串的最长公共字串. 法1: 二分长度+hash 传送门 法2: 二分+后缀数组 传送门 法3: 后缀自动机 拿第一个串建自动机,然后用其他串在上面匹配.每次求出SAM上每个节点的最长匹配长度后,再 ...

  5. BZOJ 2946 POI2000 公共串 后缀自动机(多串最长公共子串)

    题意概述:给出N个字符串,每个串的长度<=2000(雾...可能是当年的年代太久远机子太差了),问这N个字符串的最长公共子串长度为多少.(N<=5) 抛开数据结构,先想想朴素做法. 设计一 ...

  6. BZOJ 2946 [Poi2000]公共串 ——后缀自动机

    任意选择一个串作为模式串,构建出后缀自动机. 然后用其他的串在后缀自动机上跑匹配. 然后就到了理解后缀自动机性质的时候. 在某一个节点的最大值是可以沿着parent树上传的. 然后用dp[i][j]表 ...

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

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

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

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

  9. 【BZOJ】2946: [Poi2000]公共串

    http://www.lydsy.com/JudgeOnline/problem.php?id=2946 题意:给n个串,求最大公共子串.(1<=n<=5,每个串长度<=2000) ...

  10. BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案

    BZOJ_2946_[Poi2000]公共串_后缀数组+二分答案 Description          给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务: l        读入单 ...

随机推荐

  1. C语言感悟

    还没接触C语言前,以为代码是一些单词组成的公式,和背单词一样的麻烦.枯燥无味,所以英语基础的很烂的我,对C语言没什么信心. 通过这一段时间的学习,现在对C语言的认识,和最开始时很大不一样.C语言中的代 ...

  2. 20169211《Linux内核原理与分析》课程总结

    第一周作业:linux入门学习:熟悉操作linux的基础命令 第二周作业:实验反汇编一个简答的C程序,学习汇编代码的工作过程 第三周作业:学习linux内核的启动过程 第四周作业:学习linux内核进 ...

  3. HDU - 1716 排列2 水题

    排列2 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  4. NetCore+Dapper WebApi架构搭建(一):基本框架

    初衷是想用dapper搭建一个高性能的架构,因为dapper操作数据库的效率很高 1.VS创建一个NetCore WebApi的框架,然后解决方案添加一个NetStandard的类库 整个解决方案如图 ...

  5. bzoj4399 魔法少女LJJ 线段树合并

    只看题面绝对做不出系列.... 注意到\(c \leqslant 7\),因此不会有删边操作(那样例删边干嘛) 注意到\(2, 5\)操作十分的有趣,启示我们拿线段树合并来做 操作\(7\)很好处理 ...

  6. [BZOJ4883][Lydsy1705月赛]棋盘上的守卫(Kruskal)

    对每行每列分别建一个点,问题转为选n+m条边,并给每条边选一个点覆盖,使每个点都被覆盖.也就是最小生成环套树森林. 用和Kruskal一样的方法,将边从小到大排序,若一条边被选入后连通块仍然是一个环套 ...

  7. CDOJ 42/BZOJ 2753 滑雪与时间胶囊 kruskal

    2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 1376  Solved: 487[Submit][St ...

  8. POJ 1654 Area 计算几何

    #include<stdio.h> #include<string.h> #include<iostream> #include<math.h> usi ...

  9. Opencv配套的辅助工具Image Watch

    1.Image Watch 的下载链接. 2.OpenCV关于Image Watch的介绍页面链接. 3.OpenCV2.4 在线文档关于Image Watch的介绍文档. 4.更详细的信息参见I ...

  10. 客户端程序获取自己的ip、isp、地理位置等信息

    @ 比如说你需要收集用户信息,又或者要通过这些信息让用户登陆合适的服务器(北京联通用户登陆北京联通服务器). @ 淘宝和新浪都提供了类似的API,你只需要发送一个http请求,它就返回一个json格式 ...