【poj2774】 Long Long Message
http://poj.org/problem?id=2774 (题目链接)
题意
给出两个只包含小写字母的字符串,求出最长连续公共子串。
solution
第一次用后缀数组,感觉有点神。。。才发现原来sa[0]是没用的。。
将两个字符串合并为一个,并用分隔符隔开。之后跑后缀数组,求出height[],for一遍,找到在分隔符两侧的height值最大的便是答案。
UPD 2017.1.11:
我以前写的什么东西。。贴一个板子,还是习惯下标从1开始→_→
代码
// poj2774
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<set>
#define LL long long
#define inf 1<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=200010;
int rank[maxn],height[maxn],sa[maxn];
char s[maxn],s1[maxn]; namespace Suffix {
int wa[maxn],wb[maxn],ww[maxn];
int cmp(int *r,int a,int b,int l) {
return r[a]==r[b] && r[a+l]==r[b+l]; //这样写不会造成数组越界
}
void da(char *r,int *sa,int n,int m) {
int i,j,p,*x=wa,*y=wb;
for (i=0;i<=m;i++) ww[i]=0; //将桶清空
for (i=1;i<=n;i++) ww[x[i]=r[i]]++; //x记录名次
for (i=1;i<=m;i++) ww[i]+=ww[i-1]; //前缀和
for (i=n;i>=1;i--) sa[ww[x[i]]--]=i; //从n for到1和从1 for到n都可以
for (p=1,j=1;p<n;j*=2,m=p) { //j代表长度;如果已经有n个排名不同的后缀则完成;排完序后m就等于p
for (p=0,i=n-j+1;i<=n;i++) y[++p]=i; //它们没有第二关键字
for (i=1;i<=n;i++) if (sa[i]>j) y[++p]=sa[i]-j; //第二关键字排序
for (i=0;i<=m;i++) ww[i]=0; //第一关键字排序
for (i=1;i<=n;i++) ww[x[y[i]]]++;
for (i=1;i<=m;i++) ww[i]+=ww[i-1];
for (i=n;i>=1;i--) sa[ww[x[y[i]]]--]=y[i]; //这里一定要从n for 到1
for (swap(x,y),x[sa[1]]=p=1,i=2;i<=n;i++) //将名次储存在x里面
x[sa[i]]=cmp(y,sa[i-1],sa[i],j) ? p : ++p;
}
}
void calheight(char *r,int *sa,int n) {
for (int i=1;i<=n;i++) rank[sa[i]]=i;
for (int k=0,i=1;i<=n;i++) {
if (k) k--;
int j=sa[rank[i]-1];
while (s[i+k]==s[j+k]) k++;
height[rank[i]]=k; //注意这里是rank[i]
}
}
} int main() {
scanf("%s%s",s+1,s1+1);
int n=strlen(s+1);
int n1=strlen(s1+1);
s[++n]='#';int l=n;
for (int i=1;i<=n1;i++) s[n+i]=s1[i];
n+=n1;
using namespace Suffix;
da(s,sa,n,200);
calheight(s,sa,n);
int ans=0;
for (int i=2;i<=n;i++)
if ((sa[i-1]<l && sa[i]>l) || (sa[i-1]>l && sa[i]<l))
ans=max(ans,height[i]);
printf("%d",ans);
return 0;
}
Solution
后缀自动机。
将一个串构成后缀自动机以后,另一个串在上面匹配就可以了,跳par的时候长度也要更新。
代码
// poj2774
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#define LL long long
#define inf 1<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=100010;
int n;
char s[maxn]; namespace SAM {
int last,Dargen,sz;
int len[maxn<<1],ch[maxn<<1][26],par[maxn<<1];
void Extend(int c) {
int np=++sz,p=last;last=np;
len[np]=len[p]+1;
for (;p && !ch[p][c];p=par[p]) ch[p][c]=np;
if (!p) par[np]=Dargen;
else {
int q=ch[p][c];
if (len[q]==len[p]+1) par[np]=q;
else {
int nq=++sz;len[nq]=len[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
par[nq]=par[q];
par[np]=par[q]=nq;
for (;p && ch[p][c]==q;p=par[p]) ch[p][c]=nq;
}
}
}
void build() {
Dargen=sz=last=1;
for (int i=1;i<=n;i++) Extend(s[i]-'a');
}
int query(char *s) {
int ans=0,ll=0;
int l=strlen(s+1);
for (int p=Dargen,i=1;i<=l;i++) {
while (p>1 && !ch[p][s[i]-'a']) p=par[p],ll=len[p];
if (ch[p][s[i]-'a']) {
p=ch[p][s[i]-'a'];
ll++;ans=max(ans,ll);
}
}
return ans;
}
}
using namespace SAM; int main() {
scanf("%s",s+1);
n=strlen(s+1);
build();
scanf("%s",s+1);
printf("%d",query(s));
return 0;
}
【poj2774】 Long Long Message的更多相关文章
- 【POJ2774】Long Long Message(后缀数组)
[POJ2774]Long Long Message(后缀数组) 题面 Vjudge Description Little cat在Byterland的首都读物理专业.这些天他收到了一条悲伤地信息:他 ...
- 【POJ2774】Long Long Message (后缀数组)
Long Long Message Description The little cat is majoring in physics in the capital of Byterland. A p ...
- 【POJ2774】Long Long Message(后缀数组求Height数组)
点此看题面 大致题意: 求两个字符串中最长公共子串的长度. 关于后缀数组 关于\(Height\)数组的概念以及如何用后缀数组求\(Height\)数组详见这篇博客:后缀数组入门(二)--Height ...
- 【POJ2774】Long Long Message (SA)
最长公共子串...两个字符串连在一起,中间放一个特殊字符隔开.求出height之后,枚举height,看两个后缀是不是分布于两段字符串..如果是,这个值就可以作为答案.取最大值即可. ; var c, ...
- 【poj2774】Long Long Message
用个分隔符将两个字符串连接起来,再用后缀数组求出height数组的值,找出一个height值最大并且i与i-1的sa值分别在两串字符中就好 #include<algorithm> #inc ...
- laravel 【error】MethodNotAllowedHttpException No message
Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException No message 报错原因[原理]CSRF ...
- 【后缀数组】【poj2774】【 Long Long Message】
题意: 求两个串的最长连续子串. 我的想法: 枚举第二个串...在第一个串的后缀数组中二分查找. 复杂度NlogN.最坏情况N^2 题解: (3)height 数组:定义height[i]=suffi ...
- 【JAVASCRIPT】获取触发MESSAGE事件的源IFRAME
先让发送源获取焦点,然后获取焦点元素. window.addEventListener('message',function(msg){ //做一些事来判断是不是某个iframe发送的消息 msg.s ...
- 【Linux】snmp在message中报错: /etc/snmp/snmpd.conf: line 311: Error: ERROR: This output format has been de
Apr 17 17:36:17 localhost snmpd[2810]: /etc/snmp/snmpd.conf: line 311: Error: ERROR: This output for ...
随机推荐
- Centos5.8 iptables管理
使用第三方提供的Centos5.8 vmx安装的虚拟机实例, 在安装Tomcat时发现启动后8080端口无法访问, 先检查是否selinux作了限制 查看selinux状态: sestatus 查看s ...
- 二叉树的遍历(递归,迭代,Morris遍历)
二叉树的三种遍历方法: 先序,中序,后序,这三种遍历方式每一个都可以用递归,迭代,Morris三种形式实现,其中Morris效率最高,空间复杂度为O(1). 主要参考博客: 二叉树的遍历(递归,迭代, ...
- spring:如何用代码动态向容器中添加或移除Bean ?
先来看一张类图: 有一个业务接口IFoo,提供了二个实现类:FooA及FooB,默认情况下,FooA使用@Component由Spring自动装配,如果出于某种原因,在运行时需要将IFoo的实现,则F ...
- mybatis 3.2.8 + log4j2.0.2 控制台输出sql语句
mybatis3.2.7有一个bug,使用log4j2 (2.0.2)版本时,会找不到类 ,导致启动失败,详见 https://github.com/mybatis/mybatis-3/issues/ ...
- datahub
https://help.aliyun.com/document_detail/27854.html
- 无法将分支 master 发布到远程 origin,因为远程存储库中已存在具有同一名称的分支
无法将分支 master 发布到远程 origin,因为远程存储库中已存在具有同一名称的分支.发布此分支将导致远程存储库中的分支发生非快进更新. 第一次用oschina的git设置完远程仓库后提交出现 ...
- promise的学习
为了解决回调地狱的问题,所以出现了promise的设计思想. promise的三种状态: pending 等待状态 resolved 完成状态 rejected 拒绝状态 promise的三种状态,只 ...
- 将IList转换为List
简单点说,IList<T>直接转换为List<T>可以不用考虑.IList<T>可以用至少2种方式简单的复制成List<T>:1.IList<T ...
- mac搭建mamp环境
1 先安装homebrew; 执行:cd /usr/local; 非root用户执行: ruby -e "$(curl -fsSL https://raw.githubusercontent ...
- DBVisualizer 6.0.2配置
DBVis是一款通过JDBC连接数据库的软件,理论上,可以连接任何数据库,今天,我们以DBVisualizer6.0.2免费版为例 (一)连接MySql5 1.解压压缩包至本地某路径下 2.配置环境变 ...