From 81edc0cf86cd2229f08739c4ffdff7a1970f95a3 Mon Sep 17 00:00:00 2001 From: Shine wOng <1551885@tongji.edu.cn> Date: Wed, 2 Oct 2019 16:45:50 +0800 Subject: [PATCH] finish kmp.md. --- thu_dsa/chp11/kmp.md | 102 +++++++++++++++++++++++++++++- thu_dsa/chp11/kmp_improvement.png | Bin 0 -> 54734 bytes thu_os/chp20.md | 10 +-- 3 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 thu_dsa/chp11/kmp_improvement.png diff --git a/thu_dsa/chp11/kmp.md b/thu_dsa/chp11/kmp.md index b8ad09a..c133982 100644 --- a/thu_dsa/chp11/kmp.md +++ b/thu_dsa/chp11/kmp.md @@ -27,7 +27,7 @@ kmp conclusion 应该注意到,采用`kmp`策略时,每次移动的距离只与模式串`P`有关,而与文本串`T`无关。这是因为在第`k`个位置失配后,文本串中的这`k - 1`个字符和模式串长度为`k - 1`的前缀完全相同。因此所谓“值得”对齐的位置,其实就是这`k - 1`字符构成的串,前缀和后缀自相匹配的位置。 -需要指出的是,这样的位置可能有多个,所有的这些位置都是“值得”的对齐位置,因此,为了不错过其中的任意一个对齐位置,移动距离应该取所有这些自匹配位置中最小的,也就是自匹配长度最长的。为了在`kmp`算法运行过程中,迅速更新串的对齐位置,可以对模式串`P`做预处理,将在第`k`个字符处匹配失败的最长自匹配长度,保存在`next[k]`中,以便于查询。这样,就可以实现`kmp`算法了: +需要指出的是,这样的位置可能有多个,所有的这些位置都是“值得”的对齐位置,因此,为了不错过其中的任意一个对齐位置,移动距离应该取所有这些自匹配位置移动距离中最小的,也就是自匹配长度最长的。为了在`kmp`算法运行过程中,迅速更新串的对齐位置,可以对模式串`P`做预处理,将在第`k`个字符处匹配失败的最长自匹配长度,保存在`next[k]`中,以便于查询。这样,就可以实现`kmp`算法了: ```cpp int match(char* text, char* pattern){ @@ -47,3 +47,103 @@ int match(char* text, char* pattern){ 可以看到,如果匹配成功,则同时移动文本串和模式串的指针;一旦匹配失败,就将模式串的指针移动到`next[j]`,即实现上面所说的快速移动。需要注意的是对`j < 0`情况的处理,此时相当于在模式串的左边具有一通配符,即`pattern[-1] = *;`,它可以匹配任何的字符,这样就可以将该情况与匹配成功做相同的处理。 这样,现在的主要问题就是如何构造这样一个`next`数组,即实现上面的`makeNext`函数。 + +## next的构造 + +在前面已经指出了`next`数组的语意,即对于其中的第`i`项,`next[i]`表示模式串在第`i`个位置失配时,模式串的下一个对齐位置。设子串`K = P[0, i-1]`,该位置应该满足: + +```c +K[0, next[i] - 1] = K[i - next[i] ,i - 1] +``` + +所以`next[i]`的值也等于字符串`K`的最长自匹配长度。因此,构造任意一个`next[i]`,其实就是找到`P`的一个子串`P[0, i-1]`的最长自匹配长度 + +为了高效地构造出`next[i]`,不难注意到`next[i]`的值其实在一定程度上依赖于`next[i-1]`的,这是因为如果`P[i-1] = P[next[i-1]]`,即在子串`P[0, i-2]`的最长自匹配,可以直接延伸到子串`P[0, i-1]`,所以有 + +```c +next[i] = next[i - 1] + 1; +``` + +可是如果不满足`P[i-1] = P[next[i-1]]`,则上一个位置的最长自匹配长度将在新的位置断裂,此时必有`next[i] <= next[i-1]`,所以只能到子串`P[0, next[i-1]]`中去寻找新的最长自匹配长度。由于`P[0, next[i-1]] = P[i-2-next[i-1] ,i-2]`,因此`next[next[i-1]] + 1`是`next[i]`的下一个候选值,如果有 + +```c +P[i-1] == P[next[next[i-1]]]; +``` + +则有 + +```c +next[i] = next[next[i - 1]] + 1; +``` + +否则应该重复上述过程,直到条件的确满足,或者不存在这样的一个自匹配。此时应该令`next[i] = -1`,表示与模式串左边假想的通配符`P[-1] = *`是自匹配的。因此,构造`next`表的代码如下: + +```c +int* makeNext(char* str){ + int* next; + int len, i = 0, j = -1; + for (len = 0; str[len] != '\0'; ++len); + next = new int[len]; + next[0] = -1; + while(i < len - 1){ + if(j < 0 || str[i] == str[j]) next[++i] = ++j; + else j = next[j]; + } + return next; +} +``` + +应该看到,`next`表的构造的代码非常类似于`kmp`算法,这是因为`next`的构造本质上就是模式串的自我匹配,这个过程就是利用`kmp`的思想实现的。 + +可以证明,`kmp`算法的时间复杂度是`O(m + n)`。证明如下:令`k = 2i - j`,在每一次迭代中,要么执行`i++, j++`,要么执行`j = next[j]`,其中`next[j] < j`,因此每次迭代中`k`都至少增加1,而`k`的最大值不过为`2n`,即循环至多进行`O(n)`次,每一次的时间复杂度都是`O(1)`,故总的时间复杂度为`O(n)`。 + +## kmp的改进 + +上面的`kmp`算法还存在一些缺陷,例如下面的这种情况: + +![kmp_improvement](kmp_improvement.png) + +可以注意到,在文本串的`1`这个位置,统共需要进行四次比对,然而后面的三次比对都是无意义的,因为模式串的四个字符都是`0`,而在第一次失败的比对中我们就可以知道,文本串的该字符并不是`0`,因此聪明的做法应该是直接跳过这三个不可能会成功的比对。 + +对上述的问题进行总结,目前的`kmp`算法的确充分利用了先前成功比对的`经验`,来快速移动到下一个值得的对齐位置;而它的问题在于忽略了比对失败的`教训`,而这就是它在这里低效的原因。 + +为了对`kmp`进行改进,可以在构造`next`数组时,就将这种失败的负面信息纳入考虑。一般地,对于此前的`next[i]`,必然有 + +```c +P[0, next[i] - 1] == P[i-next[i] ,i-1] +``` + +但是如果 + +```c +P[next[i]] == P[i] +``` + +那么这里的`next[i]`就是没有意义的,因为将模式串的对齐位置到`next[i]`后,下一次比对一定是失败的。因此,为了解决这个问题,只需在构造`next`数组时,对这种情况加以判断,具体的代码如下: + +```c +int* makeNext(char* str){ + int* next; + int len, i = 0, j = -1; + for (len = 0; str[len] != '\0'; ++len); + next = new int[len]; + next[0] = -1; + while(i < len - 1){ + if(j < 0 || str[i] == str[j]){ + ++i, ++j; + next[i] = (str[i] == str[j]? next[j]: j); + } + else + j = next[j]; + } + return next; +} +``` + +需要注意的是,之所以在`P[next[i]] == P[i]`时,可以直接将`next[i]`更新为`next[next[i]]`,而不需要做额外的比对以确定是否满足 + +``` +P[i] == P[next[next[i]] +``` + +是因为在此前的循环中,已经判断过`P[next[i]] != P[next[next[i]]]`了。 diff --git a/thu_dsa/chp11/kmp_improvement.png b/thu_dsa/chp11/kmp_improvement.png new file mode 100644 index 0000000000000000000000000000000000000000..d65107e9dab84f8e0b47c5f5c9cdcb0570b187ed GIT binary patch literal 54734 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

;#|6bvovx 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 JNcq{D{{#3)_4)t+ literal 0 HcmV?d00001 diff --git a/thu_os/chp20.md b/thu_os/chp20.md index 491768c..ef3d600 100644 --- a/thu_os/chp20.md +++ b/thu_os/chp20.md @@ -26,7 +26,7 @@ ## 死锁的解决 -可以从多个方面来解决死锁问题。比如说,我可以防患于未然,一开始就从原理上完全杜绝死锁的出现,即`死锁预防`;或者可以退一步,在临了要分配资源的时候,对整个系统的状态进行检查,看如果分配了这个资源是否会出现死锁,如果的确会,就拒绝分配资源,这就是`死锁避免`;与预防措施相对,我也可以提前做好预案,即允许死锁的发生,在死锁发生后再去对系统进行调控,从而恢复正常的状态,即`死锁检测与恢复`。下面就分配讨论各种措施。 +可以从多个方面来解决死锁问题。比如说,我可以防患于未然,一开始就从原理上完全杜绝死锁的出现,即`死锁预防`;或者可以退一步,在临了要分配资源的时候,对整个系统的状态进行检查,看如果分配了这个资源是否会出现死锁,如果的确会,就拒绝分配资源,这就是`死锁避免`;与预防措施相对,我也可以提前做好预案,即允许死锁的发生,在死锁发生后再去对系统进行调控,从而恢复正常的状态,即`死锁检测与恢复`。下面就分别讨论各种措施。 ### 死锁预防 @@ -58,12 +58,12 @@ 为了找到这样的一个安全序列,需要各个进程告知操作系统其最大的资源需求量。在一个进程请求资源时,假想地将资源分配给该进程,随后对所有占有资源的进程做一次遍历,找到第一个这样的进程,它的资源需求量小于操作系统的资源剩余量,这样该进程一定可以成功执行完毕,然后将它当前占有的资源全部归还给操作系统,此时操作系统的资源剩余量就可以加上该进程的资源占有量。重复上面的过程,直到所有进程都遍历完毕,则的确存在这样一个`安全序列`,或者某一次遍历中找不到一个这样的进程,表示系统当前处于`不安全状态`。 -上述算法类似于银行家在向多个客户放贷的时候,采取的借贷分配策略,因此称之为`银行家算法(banker's algorithm`。下面给出`银行家算法`的算法描述: +上述算法类似于银行家在向多个客户放贷的时候,采取的借贷分配策略,因此称之为`银行家算法(banker's algorithm)`。下面给出`银行家算法`的算法描述: 设系统中存在`n`个进程,`m`类资源,设置一个`m`维列向量`available`,表示操作系统中各类资源的剩余数量;为了表示各个进程对每个资源的占用情况,设置一个`n x m`的矩阵`allocation`,其中第`i`行表示第`i`个进程对`m`个资源的占用情况;此外还设置两个`n x m`的矩阵`need`和`max`,分别表示每个进程对各个资源的需求量和最大需求量,容易看出, ```c -need[i, j] = max[i, j] - allocation[i, j] +need[i, j] == max[i, j] - allocation[i, j] ``` 当一个进程请求资源时,设置`m`维列向量`request`,表示对各个资源的请求量,算法流程如下: @@ -73,7 +73,7 @@ need[i, j] = max[i, j] - allocation[i, j] + 更新`availble -= request`,`allocation[i] += request, need[i] -= request`,即假想将资源分配给该进程。 + 遍历所有的进程,直到发现第一个进程,满足`need[i] < available`,将该进程标记为`finish`状态,表示加入`安全序列`中,更新`available += allocation[i]`。重复该过程,直到全部进程都加入了`安全序列`中,返回`安全状态`;否则,如果没有找到满足条件的进程,则返回`不安全状态`。 -从`银行家算法`可以看出,`不安全状态`并非就一定会发生死锁,实际上,死锁只是不安全状态的一个真子集。这是因为`银行家算法`在判断`不安全状态`的时候,总是从最坏的打算出发,即每个进程只有在得到它所要求的全部资源时,才会执行完毕并归还资源给操作系统。实际上,进程未必会申请它告知系统的最大需求量,而在进程执行的过程中,也会因为某些资源使用完毕就归还给操作系统了。 +从`银行家算法`可以看出,`不安全状态`并非就一定会发生死锁,实际上,死锁只是不安全状态的一个真子集。这是因为`银行家算法`在判断`不安全状态`的时候,总是从最坏的情况出发,即每个进程只有在得到它所要求的全部资源时,才会执行完毕并归还资源给操作系统。实际上,进程未必会申请它告知系统的最大需求量,而在进程执行的过程中,也会因为某些资源使用完毕就归还给操作系统了。 ### 死锁检测与恢复 @@ -87,7 +87,7 @@ need[i, j] = max[i, j] - allocation[i, j] 即直接将发生死锁的进程终止。最简单暴力的是把所有死锁进程给终止了,得劲是挺得劲的,这个开销未免太大。 -柔和一点的就是一次终止一个进程,直到死锁被解除。所以这里就涉及到应该选择进程被终止的问题,一般说来,总是选择优先级较低的,已经运行时间较短的,以及后台的批处理进程(交互进程留下),此外,还要考虑进程占有的资源数量,进程完成需要的资源,以及终止的进程数量越少越好。进程终止策略其实就是类似于我被清华的面试老师直接赶出了面试教室。 +柔和一点的就是一次终止一个进程,直到死锁被解除。所以这里就涉及到应该选择进程被终止的问题,一般说来,总是选择优先级较低的,已经运行时间较短的,以及后台的批处理进程(交互进程留下),此外,还要考虑进程占有的资源数量,进程完成需要的资源,以及终止的进程数量越少越好。进程终止策略其实就是类似于我被清华的面试老师直接赶出了面试教室这种情形。 > 资源抢占策略