HorsPool字符串匹配算法属于后缀匹配法
不太正规的讲就是从右往左开始匹配。
基本思想:
horspool算法将主串中匹配窗口的最后一个字符跟模式串中的最后一个字符比较。如果相等,继续从后向前对主串和模式串进行比较,直到完全相等或者在某个字符处不匹配为止(如下图中的f与d失配) 。如果不匹配,则根据主串匹配窗口中的最后一个字符在模式串中的下一个出现位置将窗口向右移动。(跳跃式匹配)
演示图如下:
理解不了基本思想也没关系,我们一边敲代码一边解释。
首先是定义函数
/*
* Pstr为文本串
* LenP是文本串的长度
* SStr是模式串
* Lens是模式串的长度
*/
int horspool(char * PStr,int LenP,char * SStr,int Lens)
前面也说了,Horspool属于跳跃式匹配
但是,跳跃时偏移的数字是要根据实际情况来决定的
这种实际情况有两种
第一种:
失配的字符不在模式串中或者是模式串的最后一个字符。
这时我们偏移的数字就是模式串的长度
第二种:
失配的字符在模式串中
这时,我们需要根据模式串匹配的最后一个字符下一次出现的位置移动的量
其中:
偏移量 = 该字符离最后一个字符的多远(多少个字符)-1
好了,现在我们就有头绪写初始化工作了
int table[256] = {0}; //用来存储偏移量
for(int i = 0;i < 256;++i)
table[i] = Lens; //将表中全部偏移量设模式串的长度
for(int j = 0;j < Lens;++j)
table[SStr[j]] = Lens - j - 1; //设置偏移量为模式串中每个字符离最后一个字符的最短距离(最小字符数)
接下来就是算法核心了
先来分析分析
循环结束条件
我们可以申明pos变量保存模式串在文本串中完全匹配后的位置
(-.-多读几遍就能理解了,跟C中的strstr函数返回值一个道理)
可以推导出
循环结束条件 = pos < 文本串的长度 - 模式串的长度
好了,搞定了循环结束条件后。
再想一下当模式串不匹配的时候,该怎么办
我们先来假设。如果文本串中没有一个字符存在于模式串中。
这时代码可以这样写
int pos = 0;
while(pos < LenP - Lens){
int j = Lens - 1;
if(j >= 0 && PStr[pos + j] == SStr[j])
j--;
if(j == -1)
return pos;
pos += Lens-1;
}
有人肯定会说, (~ ̄▽ ̄)table数组没用上啊!!!
而且这样有可能跳过可以完全匹配的字符!!
那申明那玩意有屁用?
别急,那个table就是用来解决情况2和情况1的
我们就要改造改造代码了!
int pos = 0;
while(pos < LenP - Lens){
int j = Lens - 1;
if(j >= 0 && PStr[pos + j] == SStr[j])
j--;
if(j == -1) /*字符完全匹配!*/
return pos;
pos += table[PStr[pos+Lens-1]]; /*检查最后一次匹配的字符是否在模式串中,如果没有,则直接偏移整个模式串的长度,否则根据下一次出现的位置设置偏移量*/
}
整体代码如下:
/*
* Pstr为文本串
* LenP是文本串的长度
* SStr是模式串
* Lens是模式串的长度
*/
int horspool(char * PStr,int LenP,char * SStr,int Lens){
int table[256] = {0}; //用来存储偏移量
for(int i = 0;i < 256;++i)
table[i] = Lens; //将表中全部偏移量设模式串的长度
for(int j = 0;j < Lens;++j)
table[SStr[j]] = Lens - j - 1; //设置偏移量为模式串中每个字符离最后一个字符的最短距离(最小字符数)
int pos = 0;
while(pos < LenP - Lens){
int j = Lens - 1;
if(j >= 0 && PStr[pos + j] == SStr[j])
j--;
if(j == -1) /*字符完全匹配!*/
return pos;
pos += table[PStr[pos+Lens-1]]; /*检查最后一次匹配的字符是否在模式串中,如果没有,则直接偏移整个模式串的长度,否则根据下一次出现的位置设置偏移量*/
}
reutrn -1; //如果失配,则直接返回-1
}
这是本人第一次写博客。如果有错误,请多多发邮件到
[email protected]