数据结构 字符串比较 KMP算法

KMP算法:最简单的字符串匹配算法由于需要回溯查找,时间复杂度大。而改进型的KMP算法充分利用字符串的特性,减少了主字符串回溯需要查找的时间,大大的降低了其复杂度,大小为O(n+m),n为主字符串长度,m为从字符串长度。

   下面介绍下KMP算法的步骤:

     主字符串:aabbdcacaabca     从字符串:aabca

      首先要设定指向主和从的指针i,j.KMP算法规定主指针不能回头,即网前移动后不能倒回去寻找匹配字符,那么就根据这个规定我们看下有什么变化和要求。

1.首先aabbdcacaabca的第一位和aabca的第一位比较,如果相等ij都跳到下一位比较,如果不等,i不变j调到前一位比较直到找到相等的。

i=1

 

 

 

 

 

 

 

 

 

 

 

 

a

a

b

b

d

c

a

c

a

a

b

c

a

a

 

 

 

 

 

 

 

 

 

 

 

 

j=1

 

 

 

 

 

 

 

 

 

 

 

 

 

2.同步骤1,比较了i=2i=3

 

 

i=3

 

 

 

 

 

 

 

 

 

 

a

a

b

b

d

c

a

c

a

a

b

c

a

a

a

b

 

 

 

 

 

 

 

 

 

 

 

 

j=3

 

 

 

 

 

 

 

 

 

 

3.i=3时发现c!=b,这时让从串回溯,看3.1后的演示:

 

 

 

i=4

 

 

 

 

 

 

 

 

 

a

a

b

b

d

c

a

c

a

a

b

c

a

a

a

b

c!=b

 

 

 

 

 

 

 

 

 

 

 

 

j=4

 

 

 

 

 

 

 

 

 

3.1由于i不能动,现在我们也不知道j应该在哪个值可行,那只有一个一个试。

   考虑从j-1位置依次往从字符串首靠比较合理。发先j=2处,a != b,因为只要一个不

   匹配,说明主串对应的段绝对不会与字串匹配。因此移动j-1位继续移动。

 

 

 

i=4

 

 

 

 

 

 

 

 

 

a

a

b

b

d

c

a

c

a

a

b

c

a

 

a

a

b

 

 

 

 

 

 

 

 

 

 

 

 

j=3

 

 

 

 

 

 

 

 

 

3.2这时j=2,发现也不匹配。

 

 

 

i=4

 

 

 

 

 

 

 

 

 

a

a

b

b

d

c

a

c

a

a

b

c

a

 

 

a

a

 

 

 

 

 

 

 

 

 

 

 

 

j=2

 

 

 

 

 

 

 

 

 

3.3这时j=1,发现也不匹配,现在的从串数据都比较完了,

  那么这时ij都跳到下一位比较。

 

 

 

i=4

 

 

 

 

 

 

 

 

 

a

a

b

b

d

c

a

c

a

a

b

c

a

 

 

 

a

 

 

 

 

 

 

 

 

 

 

 

 

j=1

 

 

 

 

 

 

 

 

 

 

4这时两者有从头开始比较

 

 

 

 

i=5

 

 

 

 

 

 

 

 

a

a

b

b

d

c

a

c

a

a

b

c

a

 

 

 

 

a

 

 

 

 

 

 

 

 

 

 

 

 

j=1

 

 

 

 

 

 

 

 

从上面3发现 c!=b后,有没有未卜先知的功能让从字符串的比较一下子

跳到步骤4,而省去3.13.23.3这样的累赘,不就轻松很多。呵呵,

(^_^)我们的大师K,MP就想出了省力讨好偷懒的办法

这个值怎么算到让j一下子跳到哪个位置还是有点复杂。

1.       首先规定第一个位置为00代表的意思是在这个位置的从字符和主字符串都

不匹配,两者都跳到下一个位置达到从来!比如从字符串的第一个a,如果主不是的a话那么他们都跳到下一个位置比较。

next大于0时,它的意义就是,主字符串的指针不变,从的字符串调到对应的next值位与主字符串现在的位置做比较。比如主是aadcef,从是aabca, 从的next值是aabca.其中从b的对应next值为2,也就是说当比较到b这位不匹配时,从应回溯到从2对应的位置上与主进行比较,即从的第二个a上面。

b

 

 

 

 

a

a

b

c

a

 

1

 

 

 

 

next

0

 

 

 

 

2.       1位匹配,假如第2位不匹配时,发现第1a

2a一样的值,那么next也一样。

a

b

 

 

 

a

a

b

c

a

 

 

2

 

 

 

next

0

0

 

 

 

3.       如果第3位不匹配,因为2位和3位不一样,当3不行的时候,可以把

2位移过来,且第1位与主字符串完全匹配。

a

a

c

 

 

a

a

b

c

a

 

 

 

3

 

 

next

0

0

2

 

 

4.4位不匹配时,同上可得。

a

a

b

b

 

a

a

b

c

a

 

 

 

 

4

 

next

0

0

2

1

 

5.5位不匹配时,按同样的方法。

a

a

b

c

c

a

a

b

c

a

 

 

 

 

 

5

next

0

0

2

1

0

说个一般性规律,还真不好说,我现在只是意会到了,言传太难了!!!

详细请看源代码:

#include <stdio.h> #include <stdlib.h> #include <string.h> //计算nextValue的值 //其中不明白的地方是 int getNext( const char t[], int next[] ) { unsigned int i,j; i = 1; next[1] = 0; //第一个必定为0 j = 0; while( i < ( strlen( t )+1 ) ) { if( j==0 || ( ( j > 0 ) && ( t[i-1] == t[j-1] ) ) ) { i++; j++; if( t[i-1] != t[j-1] ) { next[i] = j; } else { next[i] = next[j]; } } else { j = next[j]; } } return 1; } int main( void ) { char *s = “aavnsghsabc”; //随机设置字符串 char *t = “abaabcac”; int t_len, s_len; int pos=-1; int i,j,k; int *next; t_len = strlen( t ); s_len = strlen( s ); next = ( int * )malloc( sizeof( int ) * ( t_len+2 ) ); getNext( t, next ); //计算出从字符串的nextValue值 for( j = 0; j < t_len+1; j++ ) next[j] = next[j+1]; //将nextValue值平移到从数组0开始位置 i = 0; j = 0; while( i < (s_len+1 ) && j < ( t_len+1 ) ) {//寻找相匹配的位置 if( s[i] == t[j] ) { i++; j++; } else { k = next[j]; if( k == 0 ) { j++; i++; } else { j = k – 1; } } if( t[j] == ‘/0’ ) pos = i – j + 1; } if( pos > 0 ) { printf( “在%d的个位置找到相同的字符串/n”, pos ); } else { printf( “没有找到相匹配的字符串/n” ); } if( next ) free( next ); return 0; }

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/cheneagle/article/details/4393780
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞