kmp.c

来自「自己编写的一个KMP字符串匹配算法的实现」· C语言 代码 · 共 149 行

C
149
字号
 

#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;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?