前缀数等于后缀

时间:2017-11-10 13:35:31

标签: string algorithm suffix

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

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

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分:2)

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

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

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

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]。将整个长度视为特殊情况。

(注意我的while循环和KMP循环之间的相似性。如果你仍然感到困惑,我强烈建议彻底阅读/理解KMP。很容易对此有一个全面的了解,但深刻的理解是真的回答这样的问题很难也很重要。)