子串比较

时间:2016-01-22 23:40:02

标签: algorithm text

鉴于字符串s对查询(i, j, k, l)快速响应:

  • -1 if s[i..j] < s[k..l]
  • 0 if s[i..j] = s[k..l]
  • 1 if s[i..j] > s[k..l]

假设

  • i <= j
  • k <= l
  • 0 <= i, k < s.length - 1

换句话说,执行大量的词典子字符串比较。

s[i..j]是一个(j - i + 1) - 字符子字符串,从位置i开始(从0开始索引)并在位置j(包括端点)结束。

s[i..j] < s[i..j+1],这个单词的前缀被认为小于单词本身。

由于查询的数量为O(s.length),因此应快速回答查询,即以对数或恒定时间进行查询。我听说有传言说可以实现恒定时间解决方案(显然有一些预处理)。

到目前为止,我考虑使用散列函数,例如

h[i] = (h[i - 1] + x^i * s[i]) mod m

其中x > 26(字母表的大小)和m为素数。

s[i..j]的哈希值将通过从h[i]中减去h[j]并将x除以(尚未确定的)幂来计算。

这种方法有一个重要问题 - 它不允许我检查少于/大于条件。我最初认为h[i..j] < h[k..l]应该暗示s[i..j] < s[k..l]。这是无效的,因为

  1. 模。
  2. 让我们考虑字符串azzzb,让我们假设m足够大,以便我们不必执行模运算。很明显h['azzz'] > h['b']azzz < b
  3. 这是作业。我不是在寻找实现,而是我应该了解更多的一般性想法和问题。完整的解决方案当然是受欢迎的,但不是必需的。

2 个答案:

答案 0 :(得分:1)

我猜你是来自波兰,所以这里有很棒的文章,对这个问题非常好: http://www.mimuw.edu.pl/~jrad/wpg/drobne_oszustwo.pdf

实际上,您可以使用散列来检查哪个单词更大。您必须使用bin搜索来查找这两个子字符串的第一个后缀,它们具有不同的哈希值,然后检查下一个字母。这将表明更多的话。复杂度为O(logm),其中m是较短子字符串的大小。你可以在O(1)中找到哈希(使用权力的预处理),然后在O(logm)的bin搜索中找到哈希。希望它有所帮助:)

答案 1 :(得分:0)

有许多微不足道的案例可以让查询立即返回,无需预处理。这是分而治之的方法。将问题分解为子问题(在这种情况下使用Python语言):

# compare the first character of the substrings
if s[i] < s[k]:
    return -1
if s[i] > s[k]:
    return 1
# first characters are the same
if i == k:       # same substring?
    if j > l:    # first substring is longer
        return 1
    if j < l:    # second substring is longer
        return -1
    return 0     # identical substring
# worst case: same first character but different substrings
# compare s[(i+1)..j], s[(k+1)..l], maybe with a hash

希望这减少了您的问题集。我认为可能有更聪明的哈希函数。