我不想直接解决这个问题的根源问题,但问题是link:
所以我接受字符串并将它们添加到后缀数组中,该数组在内部实现为有序集,然后我获得的是两个给定字符串的按字典顺序排序的列表。
S1 = "banana"
S2 = "panama"
SuffixArray.add S1, S2
为了有效搜索k-th
最小子字符串,我预先处理这个有序集合,以添加有关后缀和它的前任之间最长公共前缀的信息,以及保持对累积子字符串计数的标记。所以我知道,对于给定的k
大于最后一项的累积子串数,这是一个无效的查询。
这适用于小输入以及问题定义中给出的约束的随机大输入,最多50个长度为2000的字符串。我能够通过7个案例中的4个并且非常惊讶我没有全部收到。
所以我去寻找瓶颈,它击中了我。给出大量像这样的输入
anananananananana.....ananana
bkbkbkbkbkbkbkbkb.....bkbkbkb
对第k个最小子串的查询仍然如预期的那样快但不是我预处理有序集的方式 ...我计算集合元素之间最长公共前缀的方式是没有效率和线性O(m),像这样,我做了最天真的事情,期待它足够好:
m = anananan
n = anananana
Start at 0 and find the point where `m[i] != n[i]`
就是这样,因为后缀和他的前任可能没有关联(即来自不同的输入字符串)所以我认为我忍不住使用蛮力。
这是问题,然后我最终减少了问题。给出一个按字典顺序排序的后缀列表,就像我上面描述的那样(由多个字符串组成):
计算最长公共前缀数组的有效方法是什么?。
那么问题就是,我的方法完全不合适吗?如果是这种情况,请提出进一步的调查途径。
脚注,我不想显示已实现的算法,我不介意被告知要阅读某某关于这个主题的书或资源,因为这是我在尝试这些挑战时所做的事情的
接受的答案将引导我走上正确的道路或在失败的情况下;能告诉我如何在更广泛的意义上解决这些类型的问题,书籍或其他东西
答案 0 :(得分:2)
我会推荐这个tutorial pdf from Stanford。
本教程解释了一个简单的O(nlog ^ 2n)算法,其中O(nlogn)空间用于计算后缀数组和中间结果矩阵。中间结果矩阵可用于计算O(logn)中两个后缀之间的最长公共前缀。
如果您希望自己尝试开发算法,关键是根据字符串的2 ^ k长前缀对字符串进行排序。
从教程:
让A(i,k)表示从位置i开始的长度为2 ^ k的A的子序列。 A(i,k)在A(j,k)子序列(j = 1,n)的排序数组中的位置保存在P(k,i)中。
和
使用矩阵P,可以迭代从最大k下降到0并检查A(i,k)= A(j,k)。如果两个前缀相等,则找到长度为2 ^ k的公共前缀。我们只剩下更新i和j,将它们增加2 ^ k并再次检查是否有更多的公共前缀。