我们有两个集合,A和B.这些集合中的每一个都包含字符串。 例如:A - {“abwcd”,“dwas”,“www”}和B - {“opqr”,“tops”,“ibmd”} 如何计算集合A中所有字符串中出现的子序列,但不计入集合B中的所有字符串?对于上面的例子,答案是1(子序列“w”)。
所有这一切都以最佳方式进行。我考虑过使用两次尝试,第一次将所有字符串的所有子序列放在tr中的B中然后,我开始将所有字符串的所有子序列放在trie t_A中的A中,而不更新trie如果相同之前在同一个字符串中找到了子序列(例如:如果我有字符串“aba”,我不计算子序列“a”两次)。通过这种方式,如果我在t_A中找到 n (大小为A)的子序列,我会检查它是否在t_B中,如果不是,我会计算它。但这非常慢,如果A和B的大小为15,字符串长度大约为100个字符,我的程序运行时间超过1秒。
编辑:由于任何子序列都以字符串的最后一个字符或其前面的字符结尾,因此我们不必生成所有子序列,而是以最后一个字符结尾的子序列的字符串。当我把它们推入trie时,我注意到每个节点都有1.所以如果我有字符串“abcd”,我只推“abcd”,“bcd”,“cd”和“d”,因为这应该是'特里的骨架。但这不是一个非常大的优化,我仍然在寻找更好的东西。
答案 0 :(得分:3)
您不必将A中所有字符串的所有子序列都放入trie中。 只放入有效的。在添加序列之前测试序列是否有效。我假设会员资格测试比添加新项目更快。一个较小的trie应该更快地失败成员资格测试,所以这个策略旨在尽快减少trie。
具体做法是: 将A中第一个字符串的所有子序列放入trie中。 (为了提高效率,请使用最短的字符串作为第一个)。保留一组对所有叶节点的引用。 接下来,对于B中的所有字符串,测试每个子序列以查看它是否存在于A.如果是,则删除该序列并将其作为引用。 (从B中最长的字符串开始,尽可能快地削减trie。)
现在你有最小的可能性来测试。 对于A中的所有剩余字符串,测试每个子序列以查看它是否存在于trie中。如果是,则将节点标记为有效,否则移至下一个子序列。 在每个字符串之后,从trie中删除所有无效节点,并将其余的标志重置为无效。