字符串匹配问题
2013-07-16 16:45
267 查看
KMP算法
字符串比较算法中KMP算法大名鼎鼎,其主要思想是先进行预处理,对模式字串提取出一些有用的信息,然后再进行字符串比较,就可以减少比较的次数。
而KMP的关键是对模式串的有用信息的提取,即提取什么特征值,提取出来后可以加速字符匹配的过程。
下面举个例子来说明究竟应该提取什么特征值。
字符串:abcabaabc
模式串:abaa
对于index=0的比较,此时ab相等,那接下去的index=1是没有必要了,可以省去了,因为前两个字符是ab是匹配的,说明序列有2个字符ab,那接下去再从模式字符串头开始匹配度的话,如果头不是a了,那么就可以跳过index=1这次,从index=2比较,故这个特征信息的关键是什么呢?
以下以一个模式串ababbaaba说明
其中蓝色表示没有匹配的字符,绿色表示匹配的字符,那这就是特征信息了,以后当进行字符串匹配的时候,就可以利用预先提取的特征值了。
Overlay
假设现在匹配字符串Pattern中已经匹配到了P[j-1],即P[0…j-1]都已经匹配了,但是P[j]不匹配了,
此时如果知道了P[j-1]处于前面的P[0..k-1]都匹配,则可以直接比较P[k]和T[i]了,此时提取的模式串的特征值是:overlay[j-1]=k-1],表示P[0….k] = P[i-k…i]最大的k值,即模式串最前几个和最后几个字符相同。
Next
假设现在匹配字符串Pattern中已经匹配到了P[j-1],即P[0…j-1]都已经匹配了,但是P[j]不匹配了,
此时我们取得P[j]的特征值,即next[j]=k,表示P[j-k….j-1] = P[0…k-1],现在比较P[j]和P[k]。
在kmp算法中,根据取得特征值的不同,在进行字符串匹配的时候会稍有不同,具体的算法如下:
Overlay方法:
Next方法:
// 使用next方法
int kmp_find2( const char *text, const char *pattern )
{
if ( text == NULL || pattern == NULL )
return -1;
int lenT = strlen(text);
int lenP = strlen(pattern);
int *next = new int[lenP];
getNext( pattern, next );
int i,j;
i = j = 0;
while ( i < lenT && j < lenP ) {
if ( j == -1 || text[i] == pattern[j] ) {
++i; ++j;
}
else {
j = next[j];
}
}
delete[] next;
if ( j == lenP )
return i - lenP;
else
return -1;
}
字符串比较算法中KMP算法大名鼎鼎,其主要思想是先进行预处理,对模式字串提取出一些有用的信息,然后再进行字符串比较,就可以减少比较的次数。
而KMP的关键是对模式串的有用信息的提取,即提取什么特征值,提取出来后可以加速字符匹配的过程。
下面举个例子来说明究竟应该提取什么特征值。
字符串:abcabaabc
模式串:abaa
序列 | a | b | c | a | b | a | a | b | c | |
Index=0 | a | b | a | | | | | | | |
Index=1 | | a | | | | | | | | 可用信息 |
Index=2 | | | a | | | | | | | |
Index=3 | | | | a | b | a | a | | | |
Index=4 | | | | | a | | | | | |
Index=5 | | | | | | a | b | | | |
序列 | a | b | c | a | b | a | a | b | c | |
Index=0 | a | b | a | | | | | | | |
Index=1 | | a | | | | | | | | 可用信息 |
模式串 | a | b | a | b | b | a | a | b | a |
0 | | | | | | | | | |
1 | | | | | | | | | |
2 | | | a | | | | | | |
3 | | | a | b | | | | | |
4 | | | | | | | | | |
5 | | | | | | a | | | |
6 | | | | | | | a | | |
7 | | | | | | | a | b | |
8 | | | | | | | | | a |
特征值的取法
以下说明两个说法Overlay
假设现在匹配字符串Pattern中已经匹配到了P[j-1],即P[0…j-1]都已经匹配了,但是P[j]不匹配了,
T[0] | T[1] | ……….. | | T[i-j] | …… | T[i-2] | T[i-1] | T[i] | |
| | | | P[0] | ….. | P[j-2] | P[j-1] | P[j] | |
| | | | | ….. | P[k-2] | P[k-1] | P[k] | |
Next
假设现在匹配字符串Pattern中已经匹配到了P[j-1],即P[0…j-1]都已经匹配了,但是P[j]不匹配了,
T[0] | T[1] | ……….. | | T[i-j] | …… | T[i-2] | T[i-1] | T[i] | |
| | | | P[0] | ….. | P[j-2] | P[j-1] | P[j] | |
| | | | | ….. | P[k-2] | P[k-1] | P[k] | |
在kmp算法中,根据取得特征值的不同,在进行字符串匹配的时候会稍有不同,具体的算法如下:
Overlay方法:
// 使用overlay方法 int kmp_find1( const char *text, const char *pattern ) { if ( text == NULL || pattern == NULL ) return -1; int lenT = strlen(text); int lenP = strlen(pattern); int *overlay = new int[lenP]; getOverlay( pattern, overlay ); int i,j,s; i = j = 0; s = -1; while ( i<lenT && j<lenP ) { if ( text[i] == pattern[j] ) { ++i; ++j; } else { if ( j == 0 ) { ++i; } else { j = overlay[j-1] + 1; } } } if ( j == lenP ) { s = i - lenP; } delete[] overlay; return s; }
Next方法:
// 使用next方法
int kmp_find2( const char *text, const char *pattern )
{
if ( text == NULL || pattern == NULL )
return -1;
int lenT = strlen(text);
int lenP = strlen(pattern);
int *next = new int[lenP];
getNext( pattern, next );
int i,j;
i = j = 0;
while ( i < lenT && j < lenP ) {
if ( j == -1 || text[i] == pattern[j] ) {
++i; ++j;
}
else {
j = next[j];
}
}
delete[] next;
if ( j == lenP )
return i - lenP;
else
return -1;
}
相关文章推荐
- 字符串匹配问题——KMP算法
- 字符串匹配问题-KMP总结
- 带通配符的字符串匹配问题的动态规划算法
- C++中用栈来判断括号字符串匹配问题
- 字符串匹配问题
- 字符串匹配问题(int countABC(* s) 输入任何一串字符串,计算机其
- 1005: 字符串匹配问题
- 字符串匹配问题-KMP总结
- 华为编程大赛---含有通配符的字符串匹配问题---基于正则表达式
- 字符串匹配问题——KMP算法理论
- 字符串匹配问题(栈)
- 字符串匹配问题
- CCF-训练50题-NO.6-字符串匹配问题
- 字符串匹配问题
- hihocode的map字符串匹配问题
- 字符串匹配问题
- 字符串转换成整数,字符串匹配问题
- HDU 3746 字符串匹配(字符串的最小循环节问题)
- 字符串匹配问题
- C语言 字符串匹配问题,KMP函数-失配函数