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

    KMP算法是一种高效的字符串匹配算法。

    KMP算法的特点是给定一个主串,给定一个匹配串,问匹配串在主串中出现的次数,匹配串在主串中出现的位置等。

    首先我们先看一种暴力的方法——按位对比,若匹配失败从头再来。

    我们用两个指针,一个指针i指在主串,一个指针j指在匹配串,

    如果s1[i+1]!=s2[j+1],根据暴力的思想就从头开始匹配,i=匹配开头+1,j=1;

    显然这么不优,这样太过暴力,KMP算法的核心思想就是对于匹配失败后j的位置做一个优化。

    我们来看下面这种情况

    s1='aabaac' s2='aabaabaac'

    当i=j=5的时候 显然s[i+1]!=s[j+1];

     若是按照原来暴力的想法此时应把匹配串的j调整为1,i调整为匹配开头+1;

    但我们发现匹配串有个性质就是部分回文,s1的前五个元素为aabaa,此时如果把i++,j=3便可继续匹配。

    利用这个性质,我们可以对原方法有一个很大的优化即——KMP算法。

    KMP的核心是预处理一个fail数组即确定匹配失败后,j指针应该调整到哪个位置。

    预处理的方法就是自我匹配,显然fail[1]=0;

    1 int s2_len=strlen(s2+1);
    2 int j=1;
    3 for(int i=1;i<=s2_len;i++)
    4 {
    5     while(s[i]!=s[j+1]&&j>0) j=fail[j];
    6     if(s[i]==s[j+1]) j++;
    7     fail[i]=j;
    8 }

    然后匹配匹配串与主串即可。

    全部代码洛谷P3375

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 
     6 using namespace std;
     7 
     8 int kmp[1000005],n,m;
     9 char s1[1000005],s2[1000005];
    10 
    11 int main()
    12 {
    13     scanf("%s%s",s1+1,s2+1);
    14     n=strlen(s1+1);
    15     m=strlen(s2+1);
    16     kmp[1]=0;
    17     int j=0;
    18     for(int i=2;i<=m;i++)
    19     {
    20         while(j&&s2[j+1]!=s2[i]) j=kmp[j];
    21         if(s2[j+1]==s2[i]) j++;
    22         kmp[i]=j;
    23     }
    24     j=0;
    25     for(int i=1;i<=n;i++)
    26     {
    27         while(j&&s1[i]!=s2[j+1]) j=kmp[j];
    28         if(s2[j+1]==s1[i]) j++;
    29         if(j==m)
    30         {
    31             printf("%d
    ",i-m+1);
    32             j=kmp[j];
    33         }
    34     }
    35     for(int i=1;i<=m;i++)
    36        printf("%d ",kmp[i]);
    37     return 0; 
    38 }
  • 相关阅读:
    什么是ETL?5分钟看完秒懂
    横向滚动 css
    解决echarts中横坐标值显示不全(自动隐藏)问题
    Echarts
    post 二进制流下载文件
    如何停止foreach
    日期格式 js
    cookie 属性
    HTML5 file对象和blob对象的互相转换
    前端图片压缩
  • 原文地址:https://www.cnblogs.com/Hoyoak/p/11431556.html
Copyright © 2011-2022 走看看