zoukankan      html  css  js  c++  java
  • 字符串算法 KMP算法 BF算法的升级版

    我得承认,我对KMP的理解没有达到百分百,所以在阐述解释时都不能将KMP算法的妙处讲清楚。

    一、实现思想

    •   通过对子串每一个字符进行扫描,会得出一个数组,这个数组可以用来帮助主串和子串比较时跳跃式前进(避免了一些不必要的比较)
    •   还是看图理解一下吧。(真的讲不清楚)

    二、图例实现

      BF表现出来的缺点

       KMP算法

    三、代码实现

      了解自身结构的函数,有了这个我们就可以知道在比较发生不匹配时可以跳过哪些,或者说是否要从头开始。这个函数我是看着课本的数学关系写出来的,所以我也解释不清。

     1 //得到next数组          这个函数就是用来了解自身结构的,但是妙处我描述不清楚,忏愧。
     2 int *find_next(char t[])
     3 {
     4     int len = strlen(t);
     5 
     6     int *next = new int[len]; //建立在堆区的next数组
     7 
     8     for (int i = 0; t[i] != ''; i++)
     9     {
    10 
    11         if (i == 0)
    12             next[i] = -1;
    13         else if (i == 1)
    14             next[i] = 0;
    15         else
    16             for (int p_start = i - 1; p_start > 0; p_start--) //b部分的起点总是0,p部分的终点总是i-1,p_start作为p数组的起点
    17             {
    18                 // int flag = 0;        //flag是b数组的长度                //原来我能够写出来完全是因为书本的公式,原来我还没有理解的
    19                 int a = 0;           //a先是作为b数组的起点,然后自增到终点
    20                 int b = i - p_start; //b先是作为q数组的起点,然后自增到终点
    21 
    22                 while (t[a] == t[b] && b <= i - 1)
    23                 {
    24                     // flag++;
    25                     a++;
    26                     b++;
    27                 }
    28                 if (b == p_start) //这里的一些数字关系真的是太妙了,我很难解释清楚
    29                 {
    30                     next[i] = p_start;
    31                     break;
    32                 }
    33                 else
    34                     next[i] = 0;
    35             }
    36     }
    37     return next;
    38 }

      

      KMP执行

     1 //KMP实现               有了那个next数组,我们就可以知道哪些是可以跳过的
     2 int KMP(char s[], char t[])
     3 {
     4     int *next = find_next(t);
     5     int i = 0;
     6     int j = 0;
     7     int begin = i;
     8     while (s[i] != '' && t[j] != '')
     9     {
    10         if (s[i] == t[j])
    11         {
    12             i++;
    13             j++;
    14         }
    15         else
    16         {
    17             begin = begin + j - next[j];
    18             j = next[j];
    19         }
    20         if (j == -1)
    21         {
    22             i++;
    23             j++;
    24             begin = i;
    25         }
    26     }
    27     return begin;
    28 }

      

     全部代码

     1 #include <stdio.h>
     2 #include <string.h>
     3 //得到next数组          这个函数就是用来了解自身结构的,但是妙处我描述不清楚,忏愧。
     4 int *find_next(char t[])
     5 {
     6     int len = strlen(t);
     7 
     8     int *next = new int[len]; //建立在堆区的next数组
     9 
    10     for (int i = 0; t[i] != ''; i++)
    11     {
    12 
    13         if (i == 0)
    14             next[i] = -1;
    15         else if (i == 1)
    16             next[i] = 0;
    17         else
    18             for (int p_start = i - 1; p_start > 0; p_start--) //b部分的起点总是0,p部分的终点总是i-1,p_start作为p数组的起点
    19             {
    20                 // int flag = 0;        //flag是b数组的长度                //原来我能够写出来完全是因为书本的公式,原来我还没有理解的
    21                 int a = 0;           //a先是作为b数组的起点,然后自增到终点
    22                 int b = i - p_start; //b先是作为q数组的起点,然后自增到终点
    23 
    24                 while (t[a] == t[b] && b <= i - 1)
    25                 {
    26                     // flag++;
    27                     a++;
    28                     b++;
    29                 }
    30                 if (b == p_start) //这里的一些数字关系真的是太妙了,我很难解释清楚
    31                 {
    32                     next[i] = p_start;
    33                     break;
    34                 }
    35                 else
    36                     next[i] = 0;
    37             }
    38     }
    39     return next;
    40 }
    41 
    42 //KMP实现               有了那个next数组,我们就可以知道哪些是可以跳过的
    43 int KMP(char s[], char t[])
    44 {
    45     int *next = find_next(t);
    46     int i = 0;
    47     int j = 0;
    48     int begin = i;
    49     while (s[i] != '' && t[j] != '')
    50     {
    51         if (s[i] == t[j])
    52         {
    53             i++;
    54             j++;
    55         }
    56         else
    57         {
    58             begin = begin + j - next[j];
    59             j = next[j];
    60         }
    61         if (j == -1)
    62         {
    63             i++;
    64             j++;
    65             begin = i;
    66         }
    67     }
    68     return begin;
    69 }
    70 int main(void)
    71 {
    72     char s[] = "ababadababac";
    73     char t[] = "ababac";
    74     int location = KMP(s, t);
    75     printf("location = %d
    ", location);
    76     for (int i = 0; i < strlen(t); i++)
    77     {
    78         printf("%c  ", s[location]);
    79         location++;
    80     }
    81     return 0;
    82 }
    83 /* 
    84 输出
    85 ————————————————————————
    86 location = 6
    87 a  b  a  b  a  c 
    88 ————————————————————————
    89  */
    全部代码

    四、总结

      这次虽然没能够完全理解KMP算法,但是对基本原理的印象加深了许多,并且意识到课本真的很厉害,虽然不能够很通俗易懂,但是该有的知识点都不会漏。

  • 相关阅读:
    iOS开发数据库篇—FMDB简单介绍
    SQLite简单介绍
    iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)
    使用Block在两个界面之间传值
    ios NSURLSession使用说明及后台工作流程分析
    iOS archiveRootObject 归档失败问题
    iOS开发UI篇—ios应用数据存储方式(归档)
    iOS archive(归档)
    CoreData数据库升级
    iOS开发过程中使用Core Data应避免的十个错误
  • 原文地址:https://www.cnblogs.com/coderon/p/13587241.html
Copyright © 2011-2022 走看看