KMP

来源:互联网 发布:11式榴弹发射器知乎 编辑:程序博客网 时间:2024/06/06 21:39

···············································这是一个叫前言的东西·············································
很久以前就知道有一个叫KMP(看毛片)的恶心算法了,但在学之前真心不知道这么恶心直到……(牛犇不要吐槽蒟蒻)
下面是一个自己对KMP的小总结,学得不久,可能不全面
············································这是前言和正文的分界线··············································

一、一点和字符串有关的东西
······说KMP之前先来看看字符串吧……
先来个例子:S = abbabbb
1、子串:串中任意个连续的字符组成的子序列称为该串的子串(完全可以理解为数学中的子集);
如:S的子串有ab abb abbb ……等;
2、前缀:包括串中首字母的子串;
如:S的前缀有a ab abb abba abbab abbabb abbabbb;
3、后缀:包括串中尾字符的子串;
如:S的后缀有b bb bbb abbb babbb bbabbb abbabbb;

二、NEXT数组
1、······铺垫了那么多看个题目先……
POJ 2752 Seek the Name, Seek the Fame给定一字符串S,求S中既是前缀又是后缀的子串。 ——我还没有写就不放代码了,next数组就可以了······似乎
*既是前缀又是后缀:即出现在前缀列又出现在后缀列的子串;
如:S = abbabbb 中 ab就是既是前缀又是后缀
2、next数组
对于字符串T,next[i]表示对于前缀S1…i 这个字符串,最长的一个与其等长前缀相等的后缀的长度(完全相同的(长度相等,每一位都相同)前缀、后缀的最大长度 (不考虑字符串本身))。
如:字符串 abbabbb中
next[5]:
abbab 前缀:a ab abb abba
后缀:b ab bab bbab
即为ab长度–> next[5] = 2;
3、代码实现
这里写图片描述

①nxt[1] = 0 ;for (int i = 2; i <= len; ++i)//t[i]为字符串第i位字符,nxt即为next数组/{int j = nxt[i - 1];while(j > 0 && t[i] != t[j + 1]) j = nxt[j];if (t[i] == t[j + 1]) j++;nxt[i] = j;}②void next(string T, int &next[]){int i = 1; next[1] = 0;j = 0;while (i < T[0]){if (j == 0 || T[i] == T[j]){++i;++j;if (T[i] !=  T[j])    next[i] = j;else next[i] = next[j]; }else j = next[j];}}

三、KMP算法
1、上题目 POJ 3461 Oulipo给定字符串S和T,求T在S中的出现次数。
这里写图片描述
2、KMP代码

while(p<=lens){  if(s[p]==t[j]){  ++p,++j;  if(j>lent){  puti(p-j+1);  putchar('\n');  if(j!=1)j=ne[j-1]+1;  else p++;  }  }  else{  if(j!=1)j=ne[j-1]+1;  else p++;  }}  

3、AK大神YWJ的KMP算法

int kmp(){  int ans=0,j=0;  for(int i=1; i<=l1; i++)  {  while(j&&b[j+1]!=a[i]) j=nxt[j];  if(b[j+1]==a[i]) j++;  if(j>=l2) ans++,j=nxt[j];  }  return ans;}

4、再放一种KMP函数(有注释)

int Index(SString S, SString T, int pos){/返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0。其中,T非空,1 <= pos <= StrLength(S)。/i = pos;j = 1;while (i <= S[0] && j <= T[0]){if (S[i] == T[j]){++i;++j;}//继续比较后继字符/else {i = i - j + 2;j = 1;}// 指针后退重新开始匹配 /} if (j > T[0])return i - T[0];else return 0;}//Index/

四、KMP的练习

  • hihoCoder 1015
    • 一道简单的KMP裸题
    • 然后是对自己的一点小提醒
      1、next数组对应的是模式串
      2、注意模式串和原串都要从下标’1’开始
      3、本题的ans记录的是模式串出现的次数,可根据需要更改
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;int n;char a[1000100], b[10100];int nxt[1000100];int la, lb;int main(){    scanf("%d", &n);    for (int i = 1; i <= n; ++i){        cin >> b >> a;        la = strlen(a), lb = strlen(b);        for (int j = lb; j > 0; j--) b[j] = b[j - 1];        for (int j = la; j > 0; j--) a[j] = a[j - 1];        nxt[1] = 0;        for (int j = 2; j <= lb; ++j){            int p =nxt[j - 1];            while (p > 0 && b[p + 1] != b[j]) p = nxt[p];            if(b[p + 1] == b[j]) p++;            nxt[j] = p;        }        int ans = 0, p = 0;        for (int j = 1; j <= la; ++j){            while (p && b[p + 1] != a[j]) p = nxt[p];            if (b[p + 1] == a[j]) p++;            if (p >= lb) ans++, p = nxt[p];        }        printf("%d\n", ans);        memset(a, '0', sizeof(a));        memset(b, '0', sizeof(b));    }    return 0;}
  • CJOJ P2566 字符串最大值
    • 一个对next数组使用的题目,挺简单的
    • 一点点提示和反省
      1、如abababa中,next[7]的值是由ababa ba 及 ab ababa决定的!!!(一下午都把next数组当成回文数了……)
      2、这道题比对时应倒着来(手玩一下吧)
      3、最后别忘了乘以长度
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;char t[1000100];int nxt[1000100];int ans[1000100];int maxx = 0;int main(){    scanf("%s", t + 1);    nxt[1] = 0;    int len = strlen(t + 1);    for (int i = 2; i <= len; i++){        int j = nxt[i - 1];        while (j && t[j + 1] != t[i]) j = nxt[j];        if (t[j + 1] == t[i]) nxt[i] = j + 1;    }    for (int i = len; i >= 1; --i) ans[i]++, ans[nxt[i]] += ans[i];    for (int i = 1; i <= len; ++i) maxx = max(maxx, ans[i] * i);    printf("%d\n", maxx);    return 0;}
  • hihocoder 1084 : 扩展KMP
    还没有做……

五、总结未做题

  1. hihocoder 1084 : 扩展KMP
  2. POJ 2752 Seek the Name, Seek the Fame
  3. POJ 3461 Oulipo

—— CYCKCN

0 0
原创粉丝点击