zoukankan      html  css  js  c++  java
  • 【字符串匹配】KMP算法和next数组的c/c++实现

    KMP算法基本思想有许多博客都写到了,写得也十分形象,不懂得可以参考下面的传送门,我就不解释基本思想了。本文主要给出KMP算法及next数组的计算方法(主要是很多网上的代码本人(相信应该是许多人吧)看不懂,直接拿来用也是各种问题),这里的代码封装性和优化都有待考究,但是基本能实现KMP算法

    http://www.cnblogs.com/c-cloud/p/3224788.html

      这里提醒各位看官,while循环次数不是常见的固定次数的循环,而是动态根据实际情况将大家固认为的“一趟循环”分解成几次,看代码时留意这点,对各位看官应该有所帮助。

    1.KMP的next数组生成方法。

      根据链接中的15来看,可以根据搜索的字符串strKey的长度确定分析的次数(第一次显然是0),第1-len次分析的长度刚好就是左边字符个数(1-len),相应次数的前缀后最的共同元素的最长长度为对应next数组的值。

      同时我们发现规律:根据前缀和后缀的特点,我们可以从每次分析的字符串(每次分析的字符串都不一样)的最后一个字符开始,向前进行字符匹配。

      每次匹配成功一个字符就后缀索引backIndex-1;

      每次匹配字符失败,需要判断是否已经有部分匹配的字符串,若有,应重置后缀索引backIndex=0,相应next数值为0;若无,前缀索引frontIndex+1即可

      每趟大循环,如果遇到已经计算到next的相应数值则进入分析下一组(这里组的概念类似链接的第15点的分析步骤);若遇到该组没有分析完,但是遇到了一些情况:比如说frontIndex =0,或者匹配成功一个字符,则进入大循环,但是是继续分析还没有分析完的这组

     1 void cal_next(char * strKey, int * next, int len)
     2 {
     3     int calTimes = 2;//计算次数 ,第一次肯定为零
     4     int frontIndex=0;//负责在前缀里边索引元素
     5     int backIndex = 0;//负责在后缀里边索引元素
     6     //清零
     7     for (frontIndex = 0; frontIndex < len; frontIndex++)
     8     {
     9         next[frontIndex] = 0;
    10     }
    11     frontIndex = calTimes-2;//取得可能的最大前缀和后缀的共同元素的最长的长度0-
    12     backIndex = calTimes-1;//0-
    13     while (calTimes<=len)
    14     {
    15         printf("calTimes:%d
    ",calTimes);
    16         printf("frontIdex:%d
    ", frontIndex);
    17         printf("backIdex:%d
    ", backIndex);
    18         while (frontIndex > 0 && strKey[backIndex] != strKey[frontIndex ])//最多calTimes次比较
    19         {
    20             printf("    There is a unmatched char
    ");
    21             if (next[calTimes - 1] != 0)//已经有部分字符匹配,中途出现了不匹配的字符
    22             {
    23                 next[calTimes-1] = 0;
    24                 backIndex = calTimes-1;//重置后缀索引
    25                 break;
    26             }
    27             frontIndex--;
    28         }
    29         if (frontIndex == 0 && strKey[backIndex ] != strKey[0])//最差的情况,一次都没有匹配成功
    30         {
    31             next[calTimes-1] =0;
    32             calTimes++;
    33             frontIndex = calTimes-2;
    34             backIndex = calTimes-1;
    35             printf("    There is never matched
    ");
    36         }
    37         else if (frontIndex == 0 && strKey[backIndex ] == strKey[0])//最后一个字符匹配成功
    38         {
    39             next[calTimes - 1] +=1;
    40             calTimes++;
    41             frontIndex = calTimes-2;
    42             backIndex = calTimes-1;
    43             printf("    the last char matched
    ");
    44         }
    45         else
    46         {
    47             if (frontIndex > 0 && strKey[backIndex ] == strKey[frontIndex ]) //匹配成功一个
    48             {
    49                 next[calTimes - 1]++;
    50                 backIndex -= 1;
    51                 frontIndex--;
    52                 printf("    a char matched
    ");
    53             }
    54         }
    55     }
    56 }

    2.KMP算法的实现

      这里的实现步骤其实就是算法了步骤了,应该没有什么可讲的,基本的实现思路跟next的生成方法差不多。

     1 void kmp(char * strText, char *strKey)
     2 {
     3     int *next = new int[strlen(strKey)];
     4     //计算next 数组
     5     cal_next(strKey,next,strlen(strKey));
     6     //查找
     7     int textLenght = strlen(strText);
     8     int keyLenght = strlen(strKey);
     9     int textIndex = 0;
    10     int keyIndex = 0;
    11     int successNums = 0;
    12     while (textIndex < textLenght)
    13     {
    14         while (textIndex <textLenght && strKey[keyIndex] != strText[textIndex])
    15         {
    16             printf("    There is a unmatched char
    ");
    17             if (keyIndex != 0)//已经匹配部分字符中途遇到不匹配的字符
    18             {
    19                 textIndex -= next[keyIndex-1];
    20                 printf("    keyIndex %d next %c
    ", keyIndex, strText[textIndex]);
    21                 keyIndex = 0;
    22             }else 
    23             textIndex++;
    24         }
    25         if (textIndex == textLenght )//一个都没有匹配成功(textLenght-1 时,一定是不予strKey的“相应字符匹配”,所以才会进入textIndex++)
    26         {
    27             if (successNums==0)
    28             printf("    Summary:        Never Matched
    ");
    29             else printf("    Summary:        %d Matched
    ",successNums);
    30         }
    31         else if (strKey[keyIndex] == strText[textIndex])//找到匹配的字符
    32         {
    33             keyIndex++;
    34             textIndex++;
    35             if (keyIndex == keyLenght)
    36             {
    37                 keyIndex = 0;
    38                 successNums++;
    39                 printf("    Summary:        Matched @textIndex=%d
    ", textIndex - keyLenght);
    40             }
    41             printf("    There is a Matched Char
    ");
    42         }
    43     }
    44 }

    3.main

    1 int _tmain(int argc, _TCHAR* argv[])
    2 {
    3     char Search[10] = {'a','b',''};
    4     char Text[100] = "abababdhello";
    5         kmp(Text, Search);
    6 
    7     while (1);
    8     return 0;
    9 }
     
    知行合一
  • 相关阅读:
    如何上传整个项目或者是文件夹到github
    阅读笔记16-架构师推荐:提高90%开发效率的工具推荐
    阅读笔记15-这些普通的程序猿,如今都已进阶成为技术大佬
    python爬虫——爬取淘票票正在热映电影
    阅读笔记12-Java 面试题 —— 老田的蚂蚁金服面试经历
    SOA架构设计案例分析
    阅读笔记11-孤独后厂村:30万互联网人跳不出的中国硅谷
    阅读笔记09-Java程序员必备的Intellij插件
    阅读笔记08-程序员依然是这个时代,贫寒学子翻身的不二选择
    os.path.join()
  • 原文地址:https://www.cnblogs.com/guiguzhixing/p/5873615.html
Copyright © 2011-2022 走看看