字符串的后缀也是 O(n) 中相同字符串的前缀

Posted

技术标签:

【中文标题】字符串的后缀也是 O(n) 中相同字符串的前缀【英文标题】:Suffixes of a string that are also prefix of the same string in O(n) 【发布时间】:2021-06-08 17:11:15 【问题描述】:

最近在HackerEarth平台遇到一个问题,解决问题的主要思路是找出一个字符串的哪些后缀在线性时间内也是同一个字符串的前缀(in size of string )。例如,在字符串“abcdzyabc”中,“abc”是字符串的后缀,也是它的前缀。我们需要在线性时间内找到所有这些后缀。

现在假设我有一个布尔数组,isSuffixPrefix?,大小为 n,即字符串 str 的长度。如果字符串 str 的后缀从索引 i 开始,即后缀 ,则 isSuffixPrefix?[i]true str[i...n-1] 也是同一个字符串str 的前缀,否则为false。我们如何在线性时间(如果可能)内计算这个数组?

字符串 s = "aaa" 的示例:

isSuffixPrefix?[0] = true    // as suffix s[0..2] = "aaa" is also the prefix of string s
isSuffixPrefix?[1] = true    // as suffix s[1..2] = "aa" is also the prefix of string s
isSuffixPrefix?[2] = true    // as suffix s[2..2] = "a" is also the prefix of string s

【问题讨论】:

【参考方案1】:

您的问题不完全是前缀函数,因为前缀函数被定义为长度为 n 的数组 π,其中 π[i] 是子串 s[0…i] 的最长正确前缀的长度,它也是此子字符串的后缀而不是整个字符串 但是你可以稍微调整一下函数来得到你想要的。因为前缀函数来自 [0..i] 你可以反转你想要的单词,它会给你来自 [n...i] 的数组,但你也需要反转数组本身:


def pi_prefix_suffix(pattern):
    P = list(pattern)
    m = len(pattern)
    a = [0] * m
    k = 0

    for q in range(2, m + 1):
        while k > 0 and P[k] != P[q - 1]:
            k = a[k - 1]
        if P[k] == P[q - 1]:
            k += 1
        a[q - 1] = k

    return a;
def reverse_string(x):
  return x[::-1]
  
print("abcbabacba")
print(reverse_string(pi_prefix_suffix(reverse_string("abcbabacba"))));

输出:

abcbabacba
[1, 0, 3, 2, 1, 2, 1, 0, 0, 0]

最后一件事,你说过

isSuffixPrefix?[2] = true // 因为后缀 s[2..2] = "a" 也是字符串 s 的前缀

但这在形式上是不正确的,因为后缀和前缀不能是整个单词(特别是如果单词是一个字母),根据定义,它必须是单词的一部分,如果你会考虑整个单词意味着任何前缀也是单词的后缀。 (如果您还想考虑最后一个字母,只需在数组上添加 1,因为它总是正确的)

【讨论】:

但我仍然不确定如何从这个数组中判断后缀是否也是前缀? @Hasip Timurtas 每个位置代表最长的后缀,也是整个字符串的前缀,假设数组中第 4 位的值在我的示例中为 2,这意味着最长的字符串是第 4 位的 2 个字母它对应于 abcBAbacBA (如您所见,babacba 的前缀也是字符串的后缀 2 个字母)。因此,如果您想知道是否有任何长度的前缀也是后缀,请检查该位置的值是否不为零。如果您想了解算法本身以及后缀和前缀的实际含义,我建议您阅读有关 kmp 算法和 π 函数的内容

以上是关于字符串的后缀也是 O(n) 中相同字符串的前缀的主要内容,如果未能解决你的问题,请参考以下文章

leetcode简单28实现strStr()

KMP(字符串匹配算法)

HDU - 4763 Theme Section(kmp)

leetcode-最长公共前缀

扩展KMP算法

后缀数组模板及应用小结 附加练习题*6