任何给定的子串对都具有相同的长度。必须检查许多对子字符串,因此幼稚的比较不够高效,但是我真的不能想到可以对字符串数组进行任何预处理来帮助加快比较过程。预先感谢!
提供了一个示例以供说明:
长字符串数组:
str = {"aaaaa", "aaabbcc", "abcdefgh"...}
要检查的子字符串对:
pairs = {(str[0][0..1],str[1][1..2]), (str[0][1..4],str[2][3..6]), (str[1][2..4], str[2][0..2])...}
要检查(替换为)的子字符串对:
pairs = {("aa","aa"), ("aaaa","defg"), ("abb","abc")...}
最终结果:
result = {true, false, true}
幼稚的比较将导致O(|pairs|*max(|str[i]|))
的运行时,我想对此进行改进。
答案 0 :(得分:1)
(在此处从Quora交叉发布我的答案)。
IMO,这个问题并未很清楚地陈述,但我认为它似乎在询问以下问题:给了我们一组字符串S [1],S [2],…,S [N]和一个每组查询的形式(i1,j1,i2,j2,L)。如果从S [i1]的位置j1和S [i2]的位置j2开始的长度L的字符串相差最多一个字符,则答案为“是”,否则为“否”。所有这些查询中的L值之和可能比字符串的总长度大得多。
在这种情况下,我们可以使用以下观察结果设计一种有效的算法:如果S和T是长度为L的字符串,则语句“ S和T的区别在于最多一个字符的变化”等同于“ LCP” (S,T)+ LCP(R(S),R(T))> = L-1”,其中R表示字符串反转,LCP是两个字符串的最长公共前缀的长度。
因此,为了有效地回答查询,我们只需要预处理字符串S [1],…,S [N]和R(S [1]),…,R(S [N]),以便最长公共前缀查询速度很快。这可以通过将S [1],…,S [N]串联以给出一个字符串S并构建S的suffix array和longest-common-prefix array来完成,然后对S的倒数进行相同的操作。然后,确定原始字符串的两个子字符串的LCP等效于确定S(*)的两个子字符串的LCP,这等效于LCP数组中的范围最小查询,可以通过预处理有效地对其进行回答。类似的说法也适用于原始字符串的反向和S的反向。
(*)从技术上讲,串联字符串S中的LCP可以扩展到原始字符串的边界之外。但是,只有在查询子字符串实际上相同的情况下才会发生这种情况,因此这仅意味着在答案为“是”的情况下,我们将回答“是”。
答案 1 :(得分:0)
您可以尝试使用后缀树:https://en.wikipedia.org/wiki/Suffix_tree
首先将所有字符串转换为后缀树。可以在O(n)时间完成,其中n是字符串的长度。
然后,您可以递归地尝试所有可能的字符串,以查看它们是否是至少2个字符串的子字符串。
从一个包含所有树的根的指针的集合开始。这反映出''是所有字符串的子字符串。然后为每个字符找到具有匹配子项的树的子集。例如。对于“ a”,找到集合中所有带有标记为“ a”的孩子的指针。对于任何非空集,您都找到了一个新的公共子字符串,然后递归检查更长的子字符串。
如果要允许一个差异,那么递归调用还必须包括到目前为止的差异数量。如果为1,则仅允许匹配的子代。如果它是0,那么您还可以对每个对(c1,c2)进行递归,其中一个字符串有一个子c1,另一些字符串有一个子c2。
我认为它的总体运行时间为O(n * m + m * k * m * l),其中n是字符串的最大长度,m是数字,k是找到的子字符串的数量,l找到的子字符串的最大长度。