文章目录
随机算法(Randomized Algorithms)
随机算法可分为两类:
-
第一类被称为拉斯维加斯算法。它由那些总是给出正确答案或根本不给出答案的随机算法组成。
-
第二类被称为蒙特卡罗算法。它总是给出一个答案,但有时可能会产生一个不正确的答案。然而,通过在每次运行中使用独立的随机选择重复运行该算法,产生错误答案的概率可以变得任意小。
一、随机选择(Randomized Selection)
利用随机算法改进之前所提出的寻找第k小元素的算法。
算法伪代码如下:
Input: 由n个元素组成的数组A[1…n]和整数k
Output: 第k小的元素
rselect(A,1,n,k)
def rselect(A,low,high,k):
v = random(low,high)
x = A[v]
将A[low...high]分成三部分:
A1 = {a|a<x}
A2 = {a|a=x}
A3 = {a|a>x}
if |A1| > k:
select(A1, 1, |A1|, k)
else if |A1| < k and |A1|+|A2| >= k:
return x
else if |A1| < k and |A1|+|A2| < k:
select(A3, 1, |A3|, k-|A1|-|A2|)
由此可见该算法为拉斯维加斯算法。
算法时间复杂度分析:
最坏情况:当每次循环只能排除一个值且k等于n时,算法为最坏情况。将A[low…high]中的元素分为三类时需要元素比较的次数即为A数组中元素的个数,故最坏情况时的元素比较次数为n+(n-1)+…+1=n*(n-1)/2,故最坏时间复杂度为O(N^2)。
平均情况:元素比较次数小于4n,故算法平均时间复杂度为O(N)。
二、测试字符串相等性(Testing String Equality)
假设双方A和B可以通过通信信道进行通信,我们将假定该信道非常可靠。A有一个很长的字符串x,B有一个很长的字符串y,他们想确定x=y。显然,A可以将x发送给B,B可以立即测试x=y。但考虑到使用渠道的成本,这种方法将极其昂贵。另一种选择是A从x派生出一个更短的字符串,可以作为x的“指纹”并将其发送给B,然后B将使用相同的推导来获得y的指纹,然后比较这两个指纹。如果它们相等,那么B将假定x=y;否则他会得出结论x不等于y然后将测试结果通知A。
对于字符串w,假设I(w)是由位字符串w表示的整数。指纹识别的一种方法是选择素数p,然后使用指纹函数:
如果p不是太大,则指纹Ip(x)可以作为短字符串发送。如果Ip(x)不等于Ip(y),显然x不等于y,反之不正确。也就是说,如果Ip(x)=Ip(y),那么x=y不一定是这种情况。我们将这种现象称为错误匹配(false match)。
通常,如果x不等于y但Ip(x)=Ip(y)时,p整除I(x)-I(y)。
因此,每次检查两个字符串的相等性时,我们都随机选择p,而不是事先给定p。此外,随机选择p允许重新发送另一个指纹,从而在x=y的情况下增加置信度。
算法步骤如下:
1、A从小于M的素数集中随机选择p。
2、A向B发送p和Ip(x)。
3、B检查Ip(x)=Ip(y),并确认两个字符串x和y的相等或不相等。
显然该算法为蒙特卡洛算法。
该方法的缺点是,对于固定p,存在某些字符串x和y对,该方法将始终失败。那么,设n是x和y的二进制字符串的位数,p是小于 2 n 2 2n^2 2n2的素数。错误匹配的概率为1/n。当我们重复执行这个算法k次,每次随机选择一个素数,则错误匹配的概论降低至**(1/n)^k**。
推导过程如下:
三、模式匹配(Pattern Matching)
给定一个文本字符串X=x1,x2,…,xn和一个模式Y=y1,y2,…,ym,其中m不等于n,确定图案是否显示在文本中。在不丧失一般性的情况下,我们假设文本字母表是{0, 1}。
解决这个问题最简单的方法就是在整个文本中移动模式,并在每个位置将模式与长度为m的文本部分进行比较。这种蛮力方法在最坏的情况下会导致O(mn)运行时间。
该算法遵循在文本X上滑动模式Y的相同蛮力算法,但不是将模式与每个块X(j)=xj,xj+1,…,xj+m-1进行比较,而是将模式的指纹Ip(Y)与文本块的指纹Ip(X(j))进行比较。
当我们从一个文本块转移到文本块时,新块X(j+1)的指纹可以很容易地从X(j)的指纹计算出来:
上式第一部分为所有数字向前移动一位,第二部分为去掉最高位,第三部分为加上最低位。文本块的长度为m,注意是二进制!
如果让Wp=2^m(mod p),那么我们就有了递归:
算法伪代码如下:
Input: 长度为n的文本X和长度为m的模式Y
Output: 如果Y出现在X中,则Y在X中的第一个位置;否则为0
从小于M的素数集中随机选择p
j=1
计算Wp=2^m (mod p)、Ip(Y)和Ip(Xj)
while j <= n-m+1:
if Ip(Y) == Ip(Xj):
return j
else:
使用前面的公式计算Ip(Xj+1)
j++
return 0
显然该算法为蒙特卡罗算法,
计算每一个Wp、Ip(Y)、Ip(X(1))的时间复杂度为O(m);由X(j)计算一次新块X(j+1)的指纹时间复杂度为O(1),故对于长度为n的文本指纹计算X(j+1)总的时间复杂度为O(n);故该算法的运行时间为O(n+m)。
设p是一个小于2(mn)^2的素数。错误匹配的概率为1/n。
推导过程如下:
算法转换为拉斯维加斯算法:
在任何情况下两个指纹Ip(Y)和Ip(X(j))匹配,就会测试这两个字符串是否相等。因此,我们最后给出了一个有效的模式匹配算法,该算法总是给出正确的结果,并且时间复杂度仍然是O(m+n)。