KMP模板與詳解
阿新 • • 發佈:2019-02-13
原理淺析
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;
}