题意:

求两个串的最长连续子串。

我的想法:

枚举第二个串...在第一个串的后缀数组中二分查找.

复杂度NlogN。最坏情况N^2

题解:

(3)height 数组:定义height[i]=suffix(SA[i-1])和suffix(SA[i])的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀。

(4) h[i]=height[rank[i]],也就是suffix(i)和在它前一名的后缀的最长公共前缀。

(5)LCP(i,j):对正整数i,j 定义LCP(i,j)=lcp(Suffix(SA[i]),Suffix(SA[j]),其中i,j 均为1 至n 的整数。LCP(i,j)也就是后缀数组中第i 个和第j 个后缀的最长公共前缀的长度。其中,函数lcp(u,v)=max{i|u=v},也就是从头开始顺次比较u 和v 的对应字符,对应字符持续相等的最大位置,称为这两个字符串的最长公共前缀。

2.2   几个性质

(1)LCP(i,j)=min{height[k]|i+1≤k≤j},也就是说,计算LCP(i,j)等同于询问一维数组height 中下标在i+1 到j 范围内的所有元素的最小值。

   

(1) 最长公共子串。给定两个字符串A 和B,求最长公共子串。

『解析』先将第二个字符串写在第一个字符串后面,中间用一个没有出现过的字符隔开,再求这个新的字符串的后缀数组。当suffix(sa[i-1]) 和suffix(sa[i])不是同一个字符串中的两个后缀时,max{height[i]}才是满足条件


..代码 二段 有一种WA了1万次才过
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
using namespace std;
/*
*suffix array
*倍增算法 O(n*logn)
*待排序数组长度为n,放在0~n-1中,在最后面补一个0
*build_sa( ,n+1, );//注意是n+1;
*getHeight(,n);
*例如:
*n = 8;
*num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0,其他大于0
*rank[] = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值,rank[n]必定为0无效值
*sa[] = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值,sa[0]必定为n是无效值
*height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
*
*/
const int MAXN=300000+5;
char S1[MAXN],S2[MAXN];
int sa[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];
int rank[MAXN],height[MAXN];
void build_sa(int s[],int n ,int m)
{
int i,j,p,*x=t1,*y=t2;
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[i]=s[i]]++;
for(int i=0;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(j=1;j<=n;j<<=1)
{
p=0;
for(i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=0;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(i=1;i<n;i++)
x[sa[i]]=(y[sa[i-1]]==y[sa[i]])&&(y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++;
if(p>=n) break;
m=p;
}
}
int s[MAXN];
int len1,len2,ans=0;
void getHeight(int s[],int n)
{
int i,j,k=0;
for(i=0;i<=n;i++)rank[sa[i]]=i;
for(i=0;i<n;i++)
{
if(k)k--;
j=sa[rank[i]-1];
while(s[i+k]==s[j+k])k++;
height[rank[i]]=k;
}
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
while(scanf("%s",S1)!=EOF)
{
int ans=0;
len1=strlen(S1);
scanf("%s",S2);
len2=strlen(S2);
for(int i=0;i<len1;i++) s[i]=S1[i];
s[len1]='$';
for(int i=len1+1;i<=len2+len1+1;i++) s[i]=S2[i-len1-1];
build_sa(s,len1+len2+2,256);
getHeight(s,len1+len2+1);
for(int i=2;i<=len1+len2+1;i++)
{
int MAX=max(sa[i-1],sa[i]);
int MIN=min(sa[i-1],sa[i]);
if(MAX>len1&&MIN<len1)
{
if(ans<height[i])
ans=height[i];
}
}
cout<<ans<<endl;
}
}
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
using namespace std;
/*
*suffix array
*倍增算法 O(n*logn)
*待排序数组长度为n,放在0~n-1中,在最后面补一个0
*build_sa( ,n+1, );//注意是n+1;
*getHeight(,n);
*例如:
*n = 8;
*num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0,其他大于0
*rank[] = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值,rank[n]必定为0无效值
*sa[] = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值,sa[0]必定为n是无效值
*height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
*
*/
const int MAXN=300000+5;
char S1[MAXN],S2[MAXN];
int sa[MAXN];
int t1[MAXN],t2[MAXN],c[MAXN];
int rank[MAXN],height[MAXN];
void build_sa(int s[],int n ,int m)
{
int i,j,p,*x=t1,*y=t2;
for(int i=0;i<m;i++) c[i]=0;
for(int i=0;i<n;i++) c[x[i]=s[i]]++;
for(int i=0;i<m;i++) c[i]+=c[i-1];
for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
for(j=1;j<=n;j<<=1)
{
p=0;
for(i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<m;i++) c[i]=0;
for(i=0;i<n;i++) c[x[y[i]]]++;
for(i=0;i<m;i++) c[i]+=c[i-1];
for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(i=1;i<n;i++)
x[sa[i]]=(y[sa[i-1]]==y[sa[i]])&&(y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++;
if(p>=n) break;
m=p;
}
}
int s[MAXN];
int len1,len2,ans=0;
void getHeight(int s[],int n)
{
int i,j,k=0;
for(i=0;i<=n;i++)rank[sa[i]]=i;
for(i=0;i<n;i++)
{
if(k)k--;
j=sa[rank[i]-1];
while(s[i+k]==s[j+k])k++;
height[rank[i]]=k;
}
}
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
while(scanf("%s",S1)!=EOF)
{
int ans=0;
len1=strlen(S1);
scanf("%s",S2);
len2=strlen(S2);
for(int i=0;i<len1;i++) s[i]=S1[i];
s[len1]='@';
for(int i=len1+1;i<=len2+len1+1;i++) s[i]=S2[i-len1-1];
build_sa(s,len1+len2+2,128);
getHeight(s,len1+len2+1);
for(int i=2;i<=len1+len2+1;i++)
{
if((long long)(sa[i]-len1)*(long long)(sa[i-1]-len1)<0) //乘爆了long long WA了无数发 真是酸爽
{
if(ans<height[i])
ans=height[i];
}
}
cout<<ans<<endl;
}
}


【后缀数组】【poj2774】【 Long Long Message】的更多相关文章

  1. 【POJ2774】Long Long Message(后缀数组)

    [POJ2774]Long Long Message(后缀数组) 题面 Vjudge Description Little cat在Byterland的首都读物理专业.这些天他收到了一条悲伤地信息:他 ...

  2. POJ2774 Long Long Message —— 后缀数组 两字符串的最长公共子串

    题目链接:https://vjudge.net/problem/POJ-2774 Long Long Message Time Limit: 4000MS   Memory Limit: 131072 ...

  3. poj2774 Long Long Message 后缀数组求最长公共子串

    题目链接:http://poj.org/problem?id=2774 这是一道很好的后缀数组的入门题目 题意:给你两个字符串,然后求这两个的字符串的最长连续的公共子串 一般用后缀数组解决的两个字符串 ...

  4. 【POJ2774】Long Long Message(后缀数组求Height数组)

    点此看题面 大致题意: 求两个字符串中最长公共子串的长度. 关于后缀数组 关于\(Height\)数组的概念以及如何用后缀数组求\(Height\)数组详见这篇博客:后缀数组入门(二)--Height ...

  5. (HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5558 Problem Description Alice wants to send a classi ...

  6. POJ 2774 Long Long Message 后缀数组

    Long Long Message   Description The little cat is majoring in physics in the capital of Byterland. A ...

  7. poj2774 后缀数组2个字符串的最长公共子串

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 26601   Accepted: 10 ...

  8. poj 2774 Long Long Message 后缀数组基础题

    Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 24756   Accepted: 10130 Case Time Limi ...

  9. POJ2774 & 后缀数组模板题

    题意: 求两个字符串的LCP SOL: 模板题.连一起搞一搞就好了...主要是记录一下做(sha)题(bi)过程心(cao)得(dan)体(xin)会(qing) 后缀数组概念...还算是简单的,过程 ...

随机推荐

  1. 第04章-VTK基础(4)

    [译者:这个系列教程是以Kitware公司出版的<VTK User's Guide -11th edition>一书作的中文翻译(出版时间2010年,ISBN: 978-1-930934- ...

  2. VS2008找不到MFC90d.dll错误解决方法

    问题是在更新嵌入的清单文件时发生的,由于FAT32的原因而未能更新嵌入的清单文件,于是我们有如下两种解决方法: (1)不启用增量链接.在项目的“属性|配置属性|链接器|常规”中的“启用增量链接”选择“ ...

  3. js中json的转换

    //aa='{"id":0,"appId":"app***********Id","appSecret":"a ...

  4. [HeadFirst-HTMLCSS入门][第九章盒模式]

    新属性 line-height 行间距 line-height: 1.6em; border 边框 属性值 solid 实线 double 双实线 groove 一个槽 outset 外凸 inset ...

  5. Unable to run mksdcard SDK tool.

    Ubuntu 14.04,安装android studio后运行出错,sdk manager不能正常运行 Unable to run mksdcard SDK tool. 原因,缺少运行需要的库:li ...

  6. Android学习笔记—Windows下NDK开发简单示例

    该示例假设Android开发环境已经搭建完成,NDK也配置成功: 1.在Eclipse上新建Android工程,名称为ndkdemo.修改res\layout\activity_main.xml &l ...

  7. contentSize、contentInset和contentOffset

    contentSize.contentInset和contentOffset 是 scrollView三个基本的属性. contentSize: The size of the content vie ...

  8. (原)Eclipse的java中文件读写

    1 在<uses-sdk…/>下面添加permission <uses-sdk android:minSdkVersion="16" android:target ...

  9. 一种无new创建对象的方法

    var L=function(){ var obj = { age:38, live:true, job:"web dev" }; obj.name = "zhouhui ...

  10. 浅谈window.attachEvent

    以前写 JavaScript 脚本时,事件都是采用object.event = handler;的方式初始化.这种方式对于 Internet Explorer.Mozilla/Firefox 和 Op ...