1. 程式人生 > >KMP模板與詳解

KMP模板與詳解

原理淺析

zyf:

求失配的過程和最後比較的過程差不多,因為每次都是如果不匹配就跳到它失配的位置。
至於為什麼是這樣,可以想象一下失配也就是說頭和尾上的一段字串是一模一樣的,那麼我們在頭上不停地往前跳,也就相當於在結尾不停地往後跳(自己體會一下)。

KMP一開始看有點暈,你先要知道的是,它是先自己和自己弄,再和大串弄
i是a串(大串)的指標,j是b串(小串)的指標

E.G.

a b a b a b a b e
a b a b e

啊,你發現這裡炸了,因為b[1]=b[3],b[2]=b[4]你完全可以,直接這樣:

a b a b a b a b e
。。。。 a b a b e

而不是這樣:

a b a b a b a b e
. a b a b e

程式碼

原理就是這樣,程式碼實現上
預處理出這樣一個數組p[j],表示當匹配到b陣列的第j個字母而第j+1個字母不能匹配了時,新的j最大是多少。
這樣可以使得A[i-j+1..i]與B[1..j]保持匹配(此處為新的j)。
然後,下一位如果還是不能匹配,再把前一個j翻出來,再匹配一次,直到找不到相同的字首了也就是j=0了,就只能把整個串往後挪一位了

#include<cstdio>
#include<cstring>
#include<algorithm>
using
namespace std; const int maxn=1000001; char a[maxn],b[maxn]; int la,lb,p[maxn]; int main() { scanf("%s%s",a+1,b+1); la=strlen(a+1); lb=strlen(b+1); int j=0;//首先b和b自身匹配 p[1]=0; for (int i=2; i<=lb; i++)//從2開始? { while (j>0 && b[i]!=b[j+1]) j=p[j]; if (b[i]==b[j+1
]) j++; p[i]=j;//更新p } j=0; for (int i=1; i<=la; i++) { while (j>0 && a[i]!=b[j+1]) j=p[j]; if (a[i]==b[j+1]) j++; if (j==lb) { printf("%d\n",i-lb+1);//輸出子串的位置 j=p[j]; } } for (int i=1; i<=lb; i++) printf("%d ",p[i]); return 0; }