-1

我试图在长度为 n 的字符串中找到等于后缀的前缀数量及其长度。它们可以重叠,例如,如果字符串是“abacaba”,那么 ans 是长度为 1 (a) 的 {1, 3, 7} 前缀,3 是“aba”和整个字符串。前缀“a”等于后缀“a”。前缀“aba”等​​于后缀“aba”。整个字符串等于后缀。如果字符串是“aaaaa”,那么答案是 {1, 2, 3, 4, 5}。“a”、“aa”、“aaa”、“aaaa”、“aaaa”。

我只能在 O(n2) 中获取每个前缀并与相同长度的后缀进行比较。但是有没有更好的算法来解决这个问题?提前致谢

4

2 回答 2

2

散列可以在这里提供帮助

将字符串 a1a2a3a4 的哈希函数定义为 (a1 * 26^3 + a2 * 26^2 + a3 * a6^1 + a4 * 26^0) % M 其中 M 是一个大素数

现在保留两个指针,一个在开头,一个在结尾。在每次迭代中将开始指针向前移动并计算前缀的哈希值开始并在每次迭代中向后移动结束指针并计算后缀的哈希值,如果哈希值相等,则字符串相等。

hash_st = 0
hash_ed = 0
st = 0
ed = len(s)-1
while st ! = len(s) - 1:
    hash_st = (hash_st*(26) + ascii_val(s[st])) % M
    hash_ed = (ascii_val(s[ed]) * (26^st) + hash_ed) % M
    if hash_st == hash_ed:
        add_to_result(st)
于 2017-11-10T13:56:59.823 回答
2

我的方法需要 O(N) 时间来预处理字符串,然后 O(|ans array|) 来计算答案。

预处理基本上是 KMP 故障表构建部分,在除最后一个字符之外的整个字符串上。("abacab"在你的例子中)。在之前返回的表中,给定字符串(即5'b')中最后一个索引的值将是 2。这意味着与以“b”结尾的 AND 匹配的最大前缀是 2。现在,如果您的最后一个字符与前缀 ( 'a') 的第三个字符匹配,则您有一个等于前缀的后缀。( "aba")

KMP 停在那里。但是你想要所有的比赛。'b'因此,您需要找到所有前缀为“b”的匹配,而不是以最后一个字符(2 in)结尾的最大匹配。所以你继续进入 KMP 的内部循环,就像上面一样,检查当前以 'b' 结尾的匹配量(可以为零),如果下一个字符等于我们的最后一个字符。

def build_table(pat):
    table = [0]*len(pat)
    p = 0
    for i in range(1,len(pat)):
        while p>0 and pat[p]!=pat[i]: #KMP's loop i was talking about
            p = table[p-1]

        if pat[p]==pat[i]:
            table[i] = p+1
            p+=1

    return table

pat = "abracadabab"
table = build_table(pat[:-1]) #build table for "abracadaba", i.e except last 

ans = [] #to store answers
p = len(pat)-1 #last index of table building string i.e 5 or 'b'
while p>0: #the main loop
    p = table[p-1] 
    print(p)
    if pat[p]==pat[-1]:
        ans.append(p+1)

print(ans)

这对于"abacab"打印[1,3],对于"abracadabra"它的[1,4]。将整个长度视为特殊情况。

(请注意我的循环和 KMP 的循环之间的相似之处while。如果您仍然感到困惑,我强烈建议您彻底阅读/理解 KMP。很容易对此有一个整体的了解,但深入理解对于回答这样的问题非常困难且至关重要.)

于 2017-11-10T15:33:55.960 回答