zoukankan      html  css  js  c++  java
  • KMP算法

    关键概念:

    1.最大相同前后缀

    abab->ab;

    abcdabc->abc;

    ababa->aba而不是ababa;

    2.next数组的含义及其求法

    next[i]=j, 意味着模式串 i 位置之前(不包括i位置)的最大相同前后缀前缀末尾的下一位是 j

    比如模式串:abab; 对应的next[]={-1,0,0,1},

    i=0时,next[0]用-1特别标识;

    i=1时,next[1]=0,即:ab,看成“a|b”,b前面最长相同前后缀不存在,前缀末尾的下一位自然应该设置为第一个字符,即a所在的位置0

    i=2时,next[2]=0,即:aba, 看成“ab|a”理由同上,前缀末尾下一位只好设置为0

    i=3时,next[3]=1,即:abab,看成“aba|b”,这时最长相同前后缀是a,前缀下一位就是b的位置1

    要点:已知的next[i]=j,根据此时模式串 p[i] 和 p[j] 是否相等来得出 next[i+1] 等于什么。(最重要)

    这里有两个next数组的递推法则:

    1.p[i]=p[j],则:next[++i]=++j;

    2.p[i]!=p[j],则:令 j=next[j],用新的p[j]与p[i]比较。

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 
     5 void getnext(char a[],int next[]){//根据已知的next[i]=j,根据此时模式串p[i]和p[j]是否相等来得出next[i+1]等于什么
     6     int n = strlen(a);
     7     int i=0,j=-1;
     8     next[0] = -1;
     9     while(i < n){//n是数组a有效数据的长度
    10         if(j==-1 || a[i]==a[j]){//j==-1一方面使得i=0,j=-1时进入next赋值语句使得next[1]=0
    11             next[++i]=++j;
    12         }
    13         else j = next[j];
    14     }
    15 }
    16 void NewGetNext(char p[],int next[]){//改进版求next数组方法
    17     int n = strlen(p);
    18     int i=0,j=-1;
    19     next[0] = -1;
    20     while(i < n){//n是数组a有效数据的长度
    21         if(j==-1 || p[i]==p[j]){
    22             // next[++i]=++j;未改进的
    23             i++,j++;
    24             //改进后的:
    25             if(p[j] != p[i])
    26                 next[i]=j;
    27             else//如果p[j]==p[i],那么直接next[i]=j就会导致下一次模式串j位置开始的匹配 与 目标串i位置再出不匹配
    28                 next[i]=next[j];
    29             //改进后的:
    30         }
    31         else j = next[j];
    32     }
    33 }
    34 
    35 int KMP(char s[], char p[], int next[]){
    36     int i=0;
    37     int j=0;
    38     int slen=strlen(s);
    39     int plen=strlen(p);
    40     while(i<slen && j<plen){
    41         if(j==-1 || s[i]==p[j]){
    42             i++,j++;
    43         }
    44         else{
    45             j = next[j];//匹配失败(j!=-1 且 s[i]!=p[j]),则i不变,j变动,用变化后的j重新和i匹配
    46         }
    47     }
    48     if(j==plen)
    49         return i-j;//返回成功匹配(第一次)从哪里开始的位置
    50         //比如s="123abab",p="abab",最后i指向最后的b,而j也指向最后的b,7-4=3,s[3]即是开始位置
    51     else
    52         return -1;
    53 }
    54 void print(int a[],int len)//打印数组的函数
    55 {
    56     printf("开始打印
    ");
    57     for(int i=0;i<len;i++)
    58         printf("%d	", a[i]);
    59     printf("
    结束打印
    ");
    60 }
    61 int main(int argc, char const *argv[])
    62 {    
    63     char p[]="abacdababc";
    64     char s[]="123baababaab zxklchakk";
    65     int n= sizeof(p)/sizeof(char)-1;
    66     int next[n];
    67     //以下为测试语句
    68     printf("getnext:
    " );
    69     getnext(p,next);
    70     print(next,n);
    71     printf("
    Newgetnext:
    ");
    72     for(int i=0;i<sizeof(next)/sizeof(int)-1;i++) next[i]=0;
    73     NewGetNext(p,next);
    74     print(next,n);
    75     return 0;
    76 }
  • 相关阅读:
    Java08_Lambda表达式
    Java基础02
    Java基础07
    JAVA基础06
    Java基础05
    Java基础01
    面向对象与面向过程
    Java常识2
    CSS常用属性记录
    geoserver发布热力图服务
  • 原文地址:https://www.cnblogs.com/gilgamesh-hjb/p/11885390.html
Copyright © 2011-2022 走看看