我刚刚写了一个问题的答案:
这个函数应该找到两个字符串之间最长的子字符串,但是当我试图找出最坏情况的运行时间和导致这种情况的输入时,我意识到我不知道。将代码视为 C 伪代码。
// assume the shorter string is passed in as A
int lcs(char * A, char * B)
{
int length_a = strlen(A);
int length_b = strlen(B);
// This holds the length of the longest common substring found so far
int longest_length_found = 0;
// for each character in one string (doesn't matter which), look for
// incrementally larger strings in the other
// once a longer substring can no longer be found, stop
for (int a_index = 0; a_index < length_a - longest_length_found; a_index++) {
for (int b_index = 0; b_index < length_b - longest_length_found; b_index++) {
// check the next letter until a mismatch is found or one of the strings ends.
for (int offset = 0;
A[a_index+offset] != '\0' &&
B[b_index+offset] != '\0' &&
A[a_index+offset] == B[b_index+offset];
offset++) {
longest_length_found = longest_length_found > offset ? longest_length_found : offset;
}
}
}
return longest_found_length;
}
到目前为止,这是我的想法:
下面,我将假设 A 和 B 的大小大致相同,不必说 A B A,我只会说 n^3。如果这非常糟糕,我可以更新问题。
如果没有代码中的一些优化,我相信运行时是 N^3 运行时的 A B A。
但是,如果字符串不同并且从未找到过长的子字符串,那么最里面的 for 循环将退出为一个常量,从而为我们留下 A*B,对吗?
如果字符串完全相同,则该算法需要线性时间,因为每个字符串只有一次同时通过。
如果字符串相似但不相同,那么最长长度找到的将成为 A 或 B 中较小的一个的重要部分,这将划分 N ^ 3 中的一个因素,留下 N ^ 2,对吗? 我只是想了解当它们非常相似但不相同时会发生什么。
大声思考,如果在第一个字母上,您找到一个长度约为 A 长度一半的子字符串。这意味着您将运行第一个循环的 A/2 次迭代,B-(A/2) 次迭代第二个循环,然后在第三个循环中最多 A/2 次迭代(假设字符串非常相似)而没有找到更长的子字符串。假设字符串长度大致相等,即 N/2 * N/2 * N/2 = O(N^3)。
可能显示此行为的示例字符串:
A A A B A A A B A A A B A A A B
A A A A B A A A A B A A A A B A
我是关闭还是我错过了什么或误用了什么?
我很确定我可以使用 trie/前缀树做得更好,但同样,我真的很想了解这个特定代码的行为。