下面是自己写的一个KMP算法实现。P为待查找串,Q为模式串,B为预处理数组。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MATCH_DETAIL 1

#if MATCH_DETAIL
void print_strP( char* P, int num )


{
int i;

printf("\nP:%d\t", num - 1);
for ( i = 0; i < num; i++ )
printf("%3c", P[i]);
printf("\n");
}

void print_strQ( char* Q, int num, int indent )


{
int i;

printf("\nQ:%d\t", num - 1);

/**//* keep indent */
for ( i = 0; i < indent; i++ )
printf("%3c", ' ');
for ( i = 0; i < num; i++ )
printf("%3c", Q[i]);
printf("\n");
}

void print_arrB( int* B, int num, int indent )


{
int i;

printf("B:%d\t", num - 1);

/**//* keep indent */
for ( i = 0; i < indent; i++ )
printf("%3c", ' ');
for ( i = 0; i < num; i++ )
printf("%3d", B[i]);
printf("\n\n");
}

void show_status( char* P, char* Q, int* B, int s, int t)


{
if ( P == NULL || Q == NULL || B == NULL )
return;

printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
print_strP( P, s + 1 );
print_strQ( Q, t + 1, s - t );
print_arrB( B, t + 1, s - t );
}
#endif

void preprocess( char* Q, int* B )


{
int i;
int j;

if ( Q == NULL || B == NULL )
return;

i = 1;
j = 0;
B[0] = 0;

while ( Q[i] != '\0' )
{

while ( j > 0 && Q[j] != Q[i] )
{
j = B[j - 1];
}
if ( Q[j] == Q[i] )
j++;
B[i] = j;
i++;
}

#if MATCH_DETAIL
printf("preprocess string Q\n");
print_strQ( Q, strlen(Q), 0 );
print_arrB( B, strlen(Q), 0 );
#endif
}

void KMP( char* P, char* Q )


{
int i;
int j;
int *B;

if ( P == NULL || Q == NULL )
return;

B = (int *)malloc( strlen(Q) );
if ( B == NULL ) return;

preprocess(Q, B);

i = j = 0;

while ( P[i] != '\0' )
{

/**//* if Q[j] cannot match P[i], change j to proper value and stop at zero */

while ( j > 0 && Q[j] != P[i] )
{
#if MATCH_DETAIL
show_status( P, Q, B, i, j );
#endif
j = B[j - 1];
}

/**//* current characters are matched, increase j */
if ( Q[j] == P[i] )
j++;
#if MATCH_DETAIL
else
show_status( P, Q, B, i, j );
#endif
i++;


if ( Q[j] == '\0' )
{
#if MATCH_DETAIL
show_status( P, Q, B, i - 1, j - 1 );
#endif
printf("Pattern matches at shift %d\n", i - j);
// find next pattern string
j = 0;
}
}
}

int main( void )


{
char* P = "ababcabdbabcabcda";
char* Q = "abcabcd";

#if MATCH_DETAIL
printf("string P:\n");
print_strP( P, strlen(P) );
printf("string Q:\n");
print_strQ( Q, strlen(Q), 0 );
#endif

KMP( P, Q );

return 0;
}
