您的位置:首页 > 其它

字符串匹配问题

2013-07-16 16:45 267 查看
KMP算法

         字符串比较算法中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

 

 

 

         对于index=0的比较,此时ab相等,那接下去的index=1是没有必要了,可以省去了,因为前两个字符是ab是匹配的,说明序列有2个字符ab,那接下去再从模式字符串头开始匹配度的话,如果头不是a了,那么就可以跳过index=1这次,从index=2比较,故这个特征信息的关键是什么呢?

序列

a

b

c

a

b

a

a

b

c

 

Index=0

a

b

a

 

 

 

 

 

 

 

Index=1

 

a

 

 

 

 

 

 

 

可用信息

以下以一个模式串ababbaaba说明

模式串

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]

 

         此时如果知道了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]不匹配了,

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]

 

         此时我们取得P[j]的特征值,即next[j]=k,表示P[j-k….j-1] = P[0…k-1],现在比较P[j]和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