[终于有感觉了]字符串匹配的KMP算法

Matrix67大牛写的非常生动,推荐大家看看他的。


以下是连接:http://www.matrix67.com/blog/archives/115


我要说的是Matirx67大牛没有提到的预处理数组的再度优化。


对于当前假设A串到了i,B串到了j,然而A[i+1]≠B[j+1],那么j变成f[j],但是如果B[f[j]+1]依旧不等于A[i+1],那么我们还要继续找。但是这个我们可以预处理出来,经过这个处理,去除了很多匹配中的无效对比,速度增快。详见下面的Ff函数。

 

//将B串和A串进行多次匹配并输出匹配成功位置 
//by Sephiroth Lee
//date: 10/8/2010
#include <stdio.h>
#include <string.h>
#define MAXN 100010 //最大长度
char A[MAXN],B[MAXN]; 
int f[MAXN],n,m,tot;
void Init() {//读入数据 
  scanf("%s%s",A,B);
  n = strlen(A);
  m = strlen(B);
  memmove(A + 1,A,sizeof(char)*n);
  memmove(B + 1,B,sizeof(char)*m);
}
void Init_f() {//初步预处理 
  int k=0;
  for (int i = 2;i <= m;++i) {
    while ((k > 0) && (B[k + 1] != B[i]))
      k = f[k];
    if (B[k + 1] == B[i])
      ++k;
    f[i] = k;
  }
}
void Ff() {//f数组优化 
  Init_f();
  int k;
  for (int i = 1;i <= m;++i) {
    k = f[i];
    while ((k > 0) && (B[k + 1] == B[i + 1]))
      k = f[k];
    f[i] = k;
  }
}
void Solve() {//进行匹配
  Ff();
  int k = 0;
  for (int i = 1;i <= n;++i) {
    while ((k > 0) && (B[k + 1] != A[i]))
      k = f[k];
    if (B[k + 1] == A[i])
      ++k;
    if (k == m) {
      ++tot;
      printf("%d\n",i-m+1);
    }
  }
  printf("%d\n",tot);
}
int main() {//主函数 
  freopen("sample.in","r",stdin);
  freopen("sample.out","w",stdout);
  Init();
  Solve();
  return 0;
}

posted @ 2010-10-08 19:32  Sephiroth.L.  阅读(561)  评论(1编辑  收藏  举报