博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj2774
阅读量:6629 次
发布时间:2019-06-25

本文共 1970 字,大约阅读时间需要 6 分钟。

题意:给出两个字符串,求最长公共子串的长度。

分析:一道后缀数组的题,构造后缀数组有两种算法,dc3和倍增,效率分别为O(n)和O(nlogn),但前者的实现较困难。后缀数组构造后获得了3个数组,sa[i]表示所有后缀排序后的排在第i位的后缀,rank[i]表示原串从第i位到结尾的那个后缀在sa中的排名是多少。height[i]表示sa[i]和sa[i + 1]所表示的字符串的最长公共前缀的长度。本题可以利用height来做,先把两个串连接,找最大height。但是记得在把两个字符串连接时加一个特殊字符作分隔。并注意判断两个sa起始位置不在一个串的内部。之所以要加这个分隔符,首先是可以保证我们所求的两个串的起始位置在sa中是相邻的,如果不加入这个分隔符,答案中两个子串在sa中可能中间会出现一些横跨两个字符串的后缀,遇到这种不相邻的情况,需要用height在两串之间的最小值外加复杂的两串是否合法匹配的判断,例如:aaba,abaaba。如果没有判断好可能会出现abaabaaba与abaaba的匹配。而且这样一来求区间内height最小值的复杂度至少是O(nlogn)(用rmq)。

View Code
#include
<
iostream
>
#include
<
cstdlib
>
#include
<
cstring
>
#include
<
cstdio
>
using
namespace
std;
#define
N 200000
char
s[N];
//
N > 256
int
n, sa[N], height[N], rank[N], tmp[N], top[N];
void
makesa()
{
//
O(N * log N)
int
i, j, len, na;
na
=
(n
<
256
?
256
: n);
memset(top,
0
, na
*
sizeof
(
int
));
for
(i
=
0
; i
<
n; i
++
)
top[rank[i]
=
s[i]
&
0xff
]
++
;
for
(i
=
1
; i
<
na; i
++
)
top[i]
+=
top[i
-
1
];
for
(i
=
0
; i
<
n; i
++
)
sa[
--
top[rank[i]]]
=
i;
for
(len
=
1
; len
<
n; len
<<=
1
)
{
for
(i
=
0
; i
<
n; i
++
)
{
j
=
sa[i]
-
len;
if
(j
<
0
)
j
+=
n;
tmp[top[rank[j]]
++
]
=
j;
}
sa[tmp[top[
0
]
=
0
]]
=
j
=
0
;
for
(i
=
1
; i
<
n; i
++
)
{
if
(rank[tmp[i]]
!=
rank[tmp[i
-
1
]]
||
rank[tmp[i]
+
len]
!=
rank[tmp[i
-
1
]
+
len])
top[
++
j]
=
i;
sa[tmp[i]]
=
j;
}
memcpy(rank, sa, n
*
sizeof
(
int
));
memcpy(sa, tmp, n
*
sizeof
(
int
));
if
(j
>=
n
-
1
)
break
;
}
}
void
lcp()
{
//
O(4 * N)
int
i, j, k;
for
(j
=
rank[height[i
=
k
=
0
]
=
0
]; i
<
n
-
1
; i
++
, k
++
)
while
(k
>=
0
&&
s[i]
!=
s[sa[j
-
1
]
+
k])
height[j]
=
(k
--
), j
=
rank[sa[j]
+
1
];
}
int
main()
{
//
freopen("D:\\t.txt", "r", stdin);
gets(s);
int
l1
=
strlen(s);
s[l1]
=
'
$
'
;
gets(s
+
l1
+
1
);
int
len;
n
=
len
=
strlen(s);
n
++
;
s[n]
=
'
$
'
;
makesa();
lcp();
int
ans
=
0
;
for
(
int
i
=
0
; i
<
n; i
++
)
if
((sa[i]
<
l1
&&
sa[i
-
1
]
>
l1)
||
(sa[i]
>
l1
&&
sa[i
-
1
]
<
l1))
if
(height[i]
>
ans)
ans
=
height[i];
printf(
"
%d\n
"
, ans);
return
0
;
}

转载地址:http://zggpo.baihongyu.com/

你可能感兴趣的文章
centos 释放缓存
查看>>
怎么在win7让WAMP下的apache自动启动
查看>>
WIN2008R2下安装plsqldeveloper和toad
查看>>
jquery 通过点击事件获取id
查看>>
ELK学习笔记b
查看>>
Linux无人值守自动化安装详细配置流程!
查看>>
【51CTO学院三周年】我和51CTO学院的点滴
查看>>
hadoop2.4.1+hbase0.98.3实现的分布式网盘系统初步
查看>>
ibatis批量新增-自增长序列
查看>>
linux系统管理之九:rpm安装包
查看>>
Linux系统中查看日志的常用命令
查看>>
java基础(二) 自增自减与贪心规则
查看>>
VMWare View的组件
查看>>
Linux下date命令使用举例说明
查看>>
Centos6下SVN服务器(结合Apache)的搭建
查看>>
Reactor和Proactor模式
查看>>
实验:关于XPath中的13个轴
查看>>
品牌的网闸介绍
查看>>
手势滑动源码(适合新手)
查看>>
我的友情链接
查看>>