1. KMP算法:对应长度为n的目标串和长度为m的模式串,kmp算法的复杂度是o(m+n).其中o(m)的时间用于需找模式串的失效函数,o(n)的时间用于匹配。算法思想说起来比较麻烦,但是并不复杂,参考数据结构的书吧。
2. 下面给出kmp的代码search()和子串出现次数代码count().其中count()的复杂度是o(n),整体复杂度也是o(m+n).
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
void fail(const char* pat, int* f){
const int len=strlen(pat);
f[0]=-1;
for (int j=1; j < len; j++){
if (pat[j] == pat[f[j-1]+1])
f[j] = f[j-1]+1;
else {
int i=f[j-1];
while ( i >=0 && pat[j] != pat[i+1] )
i = f[i];
if (pat[j] ==pat[i+1])
f[j] = i+1;
else
f[j] = -1;
}
}
}
int search(const char* tg, const char *pt, const int* f){
const int ptLen=strlen(pt);
const int tgLen = strlen(tg);
int tgPos=0,ptPos=0;
for (; tgPos < tgLen && ptPos < ptLen;) {
if (tg[tgPos] == pt[ptPos]){
ptPos++;
tgPos++;
}
else {
if (ptPos == 0)
tgPos ++;
else
ptPos = f[ptPos-1] + 1;
}
}
return ptPos < ptLen ? -1: tgPos - ptLen;
}
int count(const char* tg, const char *pt, const int* f){
const int ptLen=strlen(pt);
const int tgLen = strlen(tg);
int tgPos=0,ptPos=0,count=0;
for (; tgPos < tgLen;) {
if (tg[tgPos] == pt[ptPos]){
ptPos++;
tgPos++;
}
else {
if (ptPos == 0)
tgPos ++;
else
ptPos = f[ptPos-1] + 1;
}
if (ptPos >= ptLen ){
count ++;
ptPos=f[ptLen-1] +1;
}
}
return count;
}
int main()
{
const char *tag="abcbcbcbc";
const char *pat="bcbc";
int len=strlen(pat);
int *f =new int[len];
fail(pat,f);
cout <<"失效函数位置:\n";
for(int i=0;i<len;++i)
cout << f[i] << '\n';
cout << "子串第一次出现的位置: \n";
cout << search(tag,pat,f) << '\n';
cout <<"子串出现的次数 : \n";
cout << count(tag,pat,f) <<'\n';
return 0;
}