给定一个长字符串数组,如果它们最多只有一个字符,我如何有效地检查给定的字符串子串(给定字符串)?

问题描述 投票:0回答:2

任何给定的子串都具有相同的长度。必须检查许多子串对,所以天真的比较不够有效,但我真的不能想到任何有助于加快比较过程的字符串数组的预处理。提前致谢!

提供了一个澄清的例子:

一个长字符串数组:

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]|))的运行时,我想改进它。

c string substring string-matching
2个回答
1
投票

(在这里交叉发布我在Quora的回答)。

国际海事组织,这个问题没有说得很清楚,但我认为它似乎在问以下问题:我们给出了一组字符串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 arraylongest-common-prefix array,然后对S的反向做同样的事情。确定两个子串的LCP。原始字符串等同于确定S(*)的两个子串的LCP,其等效于LCP阵列中的范围最小查询,其可以通过预处理有效地回答。类似的陈述适用于原始字符串的反转和S的反转。

(*)从技术上讲,连接字符串S中的LCP可以超出原始字符串的边界。但是,只有在查询子字符串实际上是相同的情况下才会发生这种情况,所以这只是意味着在答案为“是”的情况下我们会回答“是”。


0
投票

您可以尝试使用后缀树:https://en.wikipedia.org/wiki/Suffix_tree

首先将所有字符串转换为后缀树。这可以在O(n)时间内完成,其中n是字符串的长度。

然后,您可以递归尝试所有可能的字符串,以查看它们是否是至少2个字符串的子字符串。

你开始使用一组包括指向所有树的根的指针。这反映了''是所有字符串的子字符串。然后为每个char查找具有匹配子项的树的子集。例如。对于'a',找到集合中标有'a'的所有指针。对于任何非空集,您已找到一个新的公共子字符串,并递归以检查更长的子字符串。

如果您想允许一个差异,那么递归调用还必须包括到目前为止的差异数量。如果为1则仅允许匹配的子项。如果它是0,那么你也可以递归每一对(c1,c2),其中一个字符串有一个子c1而另一些字符串有一个子c2。

我认为这个的整体运行时间是O(n * m + m * k * m * l),其中n是字符串的最大长度,m是它们的数字,k是你找到的子串的数量,l是最大长度你找到的子串。

© www.soinside.com 2019 - 2024. All rights reserved.