KMP——單模式串匹配演算法 模板
阿新 • • 發佈:2018-11-30
直接上程式碼,註釋很清晰
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1000010;
int kmp[MAXN];
int la,lb,j;
char a[MAXN],b[MAXN];
int main()
{
cin>>(a+1);
cin>>(b+1);
la=strlen(a+1);
lb=strlen(b+1);
j=0;
for (int i=2;i<=lb;i++)
{
while(j&& b[i]!=b[j+1])
//此處判斷j是否為0的原因在於,如果回跳到第一個字元就不用再回跳了
j=kmp[j];
//通過自己匹配自己來得出每一個點的kmp值
if(b[j+1]==b[i])j++;
kmp[i]=j;
//i+1失配後應該如何跳
}
j=0;//j可以看做表示當前已經匹配完的模式串的最後一位的位置
//如果看不懂,你也可以理解為j表示模式串匹配到第幾位了
for(int i=1;i<=la;i++)
{
while(j&&b[j+1]!=a[i]) j=kmp[j];
//如果失配,那麼就不斷向回跳,直到可以繼續匹配
if (b[j+1]==a[i]) j++;
//如果匹配成功,那麼對應的模式串位置++
if (j==lb)
{
cout<<i-lb+1<<endl;
j=kmp[j];
//繼續匹配
}
}
for (int i=1;i<=lb;i++)
cout<<kmp[i]<<" ";
return 0;
}
例題
據說是boi2009。。。
描述 Description
給你一個字串,它是由某個字串不斷自我連線形成的。但是這個字串是不確定的,現在只想知道它的最短長度是多少.
輸入格式 Input Format
第一行給出字串的長度,1 < L ≤ 1,000,000. 第二行給出一個字串,全由小寫字母組成.
輸出格式 Output Format
輸出最短的長度
樣例輸入 Sample Input
8
cabcabca
樣例輸出 Sample Output
3
時間限制 Time Limitation
1s
題解
根據kmp(即next)陣列的性質,有i%(i-next[i])==0&&next[i]!=0
則說明字串前i位迴圈,而且迴圈節長度為:i-next[i],迴圈次數為:i/( i-next[i])
因為不要求整除,所以ans=la-next[la](這是真學到了知識,也說明,KMP演算法可能會根據next陣列的特殊性質出題,得小心啊!)
程式碼
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1000010;
inline int read()
{
int f=1,num=0;
char ch=getchar();
while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
while (isdigit(ch)) num=(num<<1)+(num<<3)+(ch^48), ch=getchar();
return num*f;
}
int kmp[MAXN];
char a[MAXN];
int main()
{
int la=read();
cin>>(a+1);
int j=0;
for (int i=2;i<=la;i++)
{
while(j&&a[i]!=a[j+1])
//此處判斷j是否為0的原因在於,如果回跳到第一個字元就不用再回跳了
j=kmp[j];
//通過自己匹配自己來得出每一個點的kmp值
if(a[j+1]==a[i])j++;
kmp[i]=j;//i+1失配後應該如何跳
}
printf("%d\n",la-kmp[la]);
//根據kmp(即next)陣列的性質,有i%(i-next[i])==0&&next[i]!=0
//則說明字串前i位迴圈,而且迴圈節長度為:i-next[i],迴圈次數為:i/( i-next[i])
//因為不要求整除,所以ans=la-next[la]
return 0;
}
當你沒成功的時候。不要沮喪,你其實比你想象的人要強,
當你成功的時候,不要張狂,你其實沒你想象的那麼強。