所以我将提供一个总体思路。如果句子结构不清楚,有人会编辑答案
好的,那么我们怎么知道二进制搜索在这里适用,假设我们取 mid = (l + (r - l)/2) 作为最长公共子数组的长度。
现在如果我们有一个长度为 L 的公共子数组,那么一定有一个长度小于 L 的公共子数组,如果两个数组没有一个长度为 L 的公共子数组,它们就不能有一个长度大于的公共子数组L. 所以现在实现二分查找应该很简单,我们检查 mid 是我们可能的长度,如果存在的话
大小为 mid 的公共子数组,如果是,则可能存在更大长度的公共子数组,因此我们将当前满足的长度存储为答案并使 l = mid + 1 ,以检查更多可能的更大长度,如果在某个二进制搜索的迭代我们看到不存在长度为 mid 的公共子数组,没有增加长度的意义,所以我们选择较低的长度,即 r = mid - 1。
用c++编写代码
int l = 1 , r = min(array1.size() , array2.size()); // taking min length of array 1 and array2
int answer = -1;
while(l <= r)
{
int mid = ( l + ( r - l) / 2);
if(check(array1 , array2 , mid))
{
answer = mid;
l = mid + 1;
}
else
r = mid - 1;
}
cout << answer << "\n";
现在问题来了,我们如何检查给定长度 L 和两个数组,如果在这个给定长度 L 的两个数组中都存在一个公共子数组,因为你必须知道实际上试图给出的散列一个 数组 的 唯一 数值 , 这样 就 可以 很 容易 地 比较 两个 不同 的 数组 , 即 两个 相同 的 数组 将 具有 相同 的 哈希 值 , 而 不同 的 数组 将 有 不同 的 哈希 .所以存在不同的散列方法,但正如您所猜测的那样,它们可能是两个不同数组具有相同散列的情况,这称为冲突,所以我们如何减少它,我们可以通过使用强散列方法来减少它,从而减少碰撞概率。其中一种方法是滚动哈希,对于更一般的想法,请查看互联网上的滚动哈希。
现在在二分查找中对 mid 的每次检查中,计算所有长度为 mid 的子数组的滚动哈希,并将其存储在 hashtable 或 set 等数据结构中。然后再次计算第二个数组中长度为 mid 的所有子数组的滚动哈希,但是这次在计算时,只检查这个哈希值是否已经被计算并存储在你的数据结构中,用于第一个数组的子数组,在哈希表中(平均查找时间是O(1)) 或设置(平均查找时间是对数),如果是,那么这个中等长度的公共子数组存在并且你返回 true 到二分搜索,但是在每次检查第二个数组中长度为 mid 的窗口之后,你不要' t 找到任何已经存在的 hash ,你返回 false。
所以假设你把 hashtable 作为一个数据结构,总的时间复杂度是
( array1.size() + array2.size() ) * log( min( array1.size() , array2.size() ) )
因为您在二进制搜索中迭代 log(min(array1.size() , array2.size()) 次,并且在每次迭代中,您通过遍历检查两个数组,计算滚动哈希并检查哈希表,即(array1 .size() + array2.size())。