【发布时间】:2012-08-10 23:58:08
【问题描述】:
我们可以使用带有后缀链接 (paper here) 的因子-oracle 来计算多个字符串的最长公共子字符串吗?这里,substring 表示原始字符串的任何部分。例如“abc”是“ffabcgg”的子字符串,而“abg”不是。
我找到了一种方法来计算两个字符串s1 和s2 的最大长度公共子字符串。它通过使用不在其中的字符连接两个字符串来工作,例如'$'。然后对于长度为i >= |s1| + 2的串联字符串s的每个前缀,我们计算其LRS(最长重复后缀)长度lrs[i]和sp[i](其LRS第一次出现的结束位置)。最后,答案是
max{lrs[i]| i >= |s1| + 2 and sp[i] <= |s1|}
我写了一个使用这种方法的C++程序,在我的笔记本电脑上|s1|+|s2| <= 200000,使用oracle因子,可以在200ms内解决问题。
s1 = 'ffabcgg'
s2 = 'gfbcge'
s = s1+'$'+s2
= 'ffabcgg$gfbcge'
p: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
s: f f a b c g g $ g f b c g e
sp: 0 1 0 0 0 0 6 0 6 1 4 5 6 0
lrs:0 1 0 0 0 0 1 0 1 1 1 2 3 0
ans = lrs[13] = 3
我知道使用后缀数组和后缀树可以高效地解决这两个问题,但是我想知道是否有使用因子oracle的方法来解决它。我对这个很感兴趣,因为因子oracle很容易构造(30行C++,suffix-array大约需要60行,suffix-tree需要150行),而且运行速度比suffix-array和suffix-tree快。
你可以在this OnlineJudge测试你的第一个问题的方法,在here测试第二个问题。
【问题讨论】:
-
@jogojapan 感谢您的耐心等待!我应该为我糟糕的英语道歉。
-
完全没有(而且我也不是母语人士)。无论如何,我认为对 SO 上的因子预言有疑问真是太好了!
-
@Ray:你/你能在任何地方分享你对因子预言机构建的实现吗?我对这个话题很感兴趣,而且我通常比正式论文更擅长阅读源代码:)
-
@500-InternalServerError 您可以在gist.github.com/ZhanruiLiang/d50bf9f17b58916c8bc7 找到代码。但是,代码很脏(编程竞赛风格),概念也很棘手,您应该阅读论文才能理解它。
-
你关心因子oracle,还是只想解决常见的子字符串问题?因为如果你只关心常见的子串问题,已经有一个线性时间算法:en.wikipedia.org/wiki/Longest_common_substring_problem
标签: algorithm automata suffix-tree suffix-array