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

问题描述

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

现在假设我有一个布尔数组,isSuffixPrefix?,大小为 n,即字符串的长度 strisSuffixPrefix?[i]true 如果字符串 str 的后缀从索引 i 开始,即 suffix 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

解决方法

你的问题不完全是前缀函数,因为前缀函数被定义为一个长度为 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,3,2,1,0]

最后一件事,你说过

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

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