串的简单模式匹配和KMP算法
所谓串就是指字符串,在计算机中是一种很常见并且很重要的数据结构,我们平时所处理的文档实际上就是字符串。而对字符串的操作中比较常见的一种就是对一个串中某子串进行定位也就是模式匹配。
其中待定位的子串称为模式串,简单模式匹配算法的思想是:从主串的第一个位置和模式串的第一个字符开始比较,如果相等,则继续逐一比较后续字符;否则从主串的第二个字符开始,再重新用上一步的方法与模式串中的字符作比较,以此类推,直到比较完模式串中的所有字符。若匹配成功则返回模式串在主串中的位置,若匹配不成功,则返回一个可区别于主串所有位置的标记,如”0”
算法实现代码:
Ps:这里串中的字符存储位置是1~length
int index(Str ste,Str substr){
int i=1,j=1,k=i;
while(i<=str.lenght;&&j<=substr.length){
if(str.ch[i]==substr.ch[j]){
i++;
j++;
}else{
j=1;
i=++k;//匹配失败,i从主串的下一个位置开始
}
}
if(j>substr.length)
return k;
else
return 0;
}
简单匹配算法思想很简单,但是时间复杂度比较大,并不是一种理想的算法,比如在一种极端情况下,0000……01,然后模式串是00001,这样的话最坏的时间复杂度是O(m*n),n,m分别为主串和模式串的长度。
而KMP算法可以在O(n+m)的时间数量级上完成串的匹配工作,其改进在于:每当一趟匹配过程中出现字符不等时不需要回溯i指针,而是利用已经得到的“部分匹配”的结果将模式向右滑动尽可能远的一段距离。
这里我们通常定义一个next[j]数组,j取1~m,m为模式串长度,表示模式串中第j个字符发生不匹配的时候,应从next[j]处的字符开始重新与主串比较。
例如一个模式串:ABABABB,当在第四个位置出现不匹配的时候,说明主串前面三个字符是ABA而模式串的前两个字符是AB所以这个时候,就可以从第三个位置开始比较,这里有两种特殊情况:
1、 模式串中的第一个字符与主串i位置不匹配,应从下一个位置和模式串第一个字符继续比较
2、 当模式串中从第一个字符到不匹配的字符的前一个字符如果不存在前后重合的部分时则从主串中发生不匹配的字符和模式串第一字符开始比较。
如ABABABB的next数组如下
模式串 | A | B | A | B | A | B | B |
j | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
next[j] | 0 | 1 | 1 | 2 | 3 | 4 | 5 |
下面是求next数组的算法:
void getNext(Strsubstr,int next[]){
int i=1,j=0;
next[i]=0;
while(i<substr.length){
if(j==0||substr.ch[i]==substr.ch[j]){
i++;
j++;
}else{
j=next[j];
}
}
}
下面是KMP算法:
int KMP(Str str,Strsubstr,int next[]){
int i=,j=1;
while(i<=str.length&&j<=substr.length){
if(j==0||str.ch[i]==substr.ch[j]){
i++;
j++;
}else{
j=next[j];
}
If(j>substr.length)
return i-substr.length;
else
return 0;
}
KMP算法优点:
1、 快 最坏的时间复杂度为O(m+n)
2、 无需回溯访问待匹配字符串S,所以对处理从外设输入的庞大文件很有效,可以边读入,边匹配。