1 //s是模式字符串,t是匹配字符串(可以看我上一篇文章中的叙述) 2 int KMP(const char * s , const char * t) 3 { 4 int slen = strlen(s) , tlen = strlen(t); 5 int i = 0 , j = 0; 6 int *next = ( int * )malloc( sizeof( int ) * slen );
7 GetNextVal( s , next); //生成部分匹配值的函数 8 while( i < slen && j < tlen ) 9 { 10 if(s[i] == t[j]) 11 { 12 i++; 13 j++; 14 } 15 else 16 if(i == 0) 17 { 18 j = j + 1;//如果第一个字符都不匹配,就直接移一位 19 } 20 else 21 { 22 //按照上一篇文章中写的,移动步数 = 已匹配字符 - 匹配值 23 //算式应该是:j = ( j - i )+ ( i - next[i-1] ) ;(j - i )为首字符所在的位置 24 //化简后为:j = j - next[i-1]; 再将匹配字符串的索引归0; i = 0; 25 //但我们发现,对于之前已经匹配的字符我们又重新比较了一次, 26 //所以进行修正,j的值不变,移动匹配字符串,即 i = next[i-1]; 27 28 i = next[i-1]; 29 } 30 }
free( next ); 31 if( i == slen ) //说明匹配成功 32 return j - slen; //返回目标字符串中匹配字符串的位置 33 else 34 return -1; //表示匹配失败 35 }
首先是KMP算法的主体,可能存在一定的代码冗余,但是是完全按照我上篇文章所写的内容写的,可能和网上的代码不太一样,但更好理解。下面插入生成部分匹配值的函数。
1 void * GetNextVal( const char *s , int *temp ) 2 { 3 int i = 0 , j = 0; 4 5 temp[0] = 0; 6 7 while( i < len) 8 { 9 i++; 10 if ( s[i] == s[j] ) 11 { 12 j++; 13 temp[i] = j; 14 } 15 else 16 { 17 j = 0; 18 if ( s[i] == s[j] ) 19 { 20 j++; 21 temp[i] == j; 22 } 23 else 24 { 25 temp[i] == j; 26 } 27 } 28 } 29 }
这个函数代码冗余量有点多,需要改进,但目前没有想到修改方法。