• KMP 算法——C


        昨天看了一下用于字符子串查找的KMP算法,很巧妙,也很难编,程序不长,理解起来可真是费劲。因为要用C语言来实现,所以书里KMP算法定义的next数组的求值方法需要改动,因为C语言里的字符串数据结构并不是让第一位存储字符串长度,而是直接保存了第一个字符,就是这样一个小小的变化,可让我伤透了脑筋,而且即便如此,对于算法的本质也不算了解得很透彻,几乎是在死命调试的情况下把程序给实现出来,里面是不是有bug也不敢确定,编程可真是件纠结的事,要是早些接触就好了,可以静静的思考,不用背负着找工作的压力来学习。

        寻找字符串的子串,结果返回第一个匹配的子串首字符的位置,从0开始。

    1.先从简单算法开始,简单算法主要是通过循环来实现。

        int Index( char* s, char* t, int pos )        /*s为目标字符串,t为要寻找的字串,pos为s中的开始位置*/

        {

            int slen, tlen;

            int i = pos, j = 0;        /*使用i标记s中的位置,使用j标记t中的位置*/

            if( s == NULL || t == NULL )

                return -1;

            slen = strlen( s );

            tlen = strlen( t );

            if( tlen > slen || pos < 0 || pos > tlen - 1 )

                return -1;

            while( i < slen && j < tlen )

            {

                if( s[i] == t[j] )

                { ++i; ++j }

                else

                { i = i - j + 1; j = 0; }        /*通过回溯i指针并将j重新指向起始位置*/

            }

            if( j >= tlen )

                return i - j;

            else

                return -1;

        }

    2.首位匹配算法

    类似简单算法,只是要先比较模式串t的首尾字符,首尾字符比较完后,再应用简单算法比较中间字符

    int Index_FL( char* s, char* t, int pos )

    {

        int slen, tlen, patStart, patEnd;

        int i = pos, j, k;

        if( s == NULL || t == NULL )

                return -1;

        slen = strlen( s );

        tlen = strlen( t );

        if( tlen > slen || pos < 0 || pos > tlen - 1 )

            return -1;

        patStart = t[0];

        patEnd = t[ tlen - 1 ];

        while( i <= slen - tlen )        /*最后一个匹配位置为i = slen - tlen*/

        {

            if( s[i] != patStart ) ++i;

            else if( s[ i + tlen - 1 ] != patEnd ) ++i;

            else

            {

                k = 1; j = 1;        /*用k来标记s中的位置, 以i + 1为起点*/

                while( j < tlen - 1 && s[ i + k ] == t[j] )        /*对中间字符串应用简单算法进行匹配*/

                { j++; k++; }

                if( j >= tlen - 1 )        /*由于末尾已经检测过相等,所以当 j = tlen - 1时表明匹配*/

                   return i;

                else        /*不匹配则i右移一位*/

                    i++; 

            }

        }

        return -1;

    }

    3.KMP算法,主要差别就在于,之前在遇到不匹配的情况时都是回溯s字符串的i指针,使用该算法则保持i不变,回溯t字符串的j指针,并且通过将t数组的首尾字串的重合位数记录在next数组中,在匹配过程中,通过next数组的值,来确定j指针的回溯位置。(说的比较抽象,具体学习还是参看教材,我这里就是做个记录便于以后复习或改进O(∩_∩)O)

    红色部分是跟原先算法主要的不同之处

    void get_next( char* t, int next[] )        /*若不存在k使得‘p0...pk-1’ = ‘pj-k...pj-1’,则令next[j] = 0(原先算法是令这种情况的next值为1)*/

    {

        int tlen;

        int i = 1, j = 0;

        next[0] = 0;

        next[1] = 0;

        tlen = strlen( t );

        while( i < tlen )

        {

            if( t[i] == t[j] )

            { ++i; ++j; next[i] = j; }

            else

            {

                j = next[j];

                if( j == 0 )        /*j == 0则代表next[i + 1] = 0,即不存在k使得‘p0...pk’ = ‘pi-k...pi’*/

                    next[++i] = 0;

            }

        }

    }

    int Index_KMP( char* s, char* t, int pos )

    {

            int slen, tlen, i, j;

            int next[100];

            if( s == NULL || t == NULL )

                return -1;

            slen = strlen( s );

            tlen = strlen( t );

            get_next( t, next );

            if( tlen > slen || pos < 0 || pos > tlen - 1 )

                return -1;

            i = pos; j = 0;

            while( i < slen && j < tlen )

            {

                if( s[i] == t[j] ) { ++i; ++j; }

                else

                {

                    if( j == 0 )        /*当s[i] != t[0]时直接将i移至下一位进行比较*/

                        ++i;

                    else

                        j = next[j];

                }

            }

            if( j >= tlen )

                return i - tlen;

            else

                return 0;

    }

        

  • 相关阅读:
    LOGO生成器
    【转】 iOS开发:Debug与Release版本NSLog屏蔽方法
    【转】IOS调试技巧:当程序崩溃的时候怎么办 iphone IOS
    【转】 Objective C实现多继承
    NSArray
    记一次 ios程序 内存优化记录LOG日志
    【转】[iOS] 关于 self = [super init];
    NSMutableArray
    Xcode调试利器 Instruments用户指南
    一段代码展现一个流程,流程在代码中内聚
  • 原文地址:https://www.cnblogs.com/liangchao/p/2695233.html
Copyright © 2020-2023  润新知