好吧,我是第一次手写KMP
参考:
1.帮助建立KMP的直觉:http://kb.cnblogs.com/page/176818/
2.具体求解方法:http://www.matrix67.com/blog/archives/115
3.非常详细的一篇,包括各种情况
http://blog.sina.com.cn/s/blog_70bab9230101g0qv.html
代码:
void produce_p(int*out,char*in)
{
out[0]=-1;
int length=strlen(in);
for(int i=1;i<length;i++)
{
int x=out[i-1];
while(in[x+1]!=in[i] && x!=-1)
{
x=out[x];
}
if(in[x+1]!=in[i])
{
out[i]=-1;
}
else
{
out[i]=x+1;
}
}
}
int kmp(char*text,char*pattern,int *p)
{
int text_len=strlen(text);
int j=0;
for(int i=0;i<text_len;)
{
while(pattern[j]!=text[i]&&j!=0)
{
j=p[j-1]+1;
}
if(pattern[j]==text[i])
{
if(j==strlen(pattern)-1)
{
return i-j;
break;
}
i++;
j++;
}
else
{
i++;
j=0;
}
}
return -1;
}
说明:
1.p相当于next数组,有一些细微的区别,不过作用差不多
2.所有下标都是从0开始
完整代码:
#include <iostream>
#include <cstring>
#include <cassert>
#include <ctime>
using namespace std;
//char pattern[]="abcdefgabcdefabcdeabcdabcaba";
char pattern[]="abaabcac";
char text[100]="acabaabaabcacaabc";
static int next[10];//more than length of pattern
static int p[10];//more than length of pattern
int produce_text(char*text,int n,char*pattern)
{
int pattern_len=strlen(pattern);
int r=rand()%(n-pattern_len-1);
for(int i=0;i<r;i++)
{
int r2=rand()%pattern_len;
text[i]=pattern[r2];
}
memcpy(text+r,pattern,pattern_len);
for(int i=r+pattern_len;i<n;i++)
{
int r2=rand()%pattern_len;
text[i]=pattern[r2];
}
text[n-1]=0;
return r;
}
void produce_p(int*out,char*in)
{
out[0]=-1;
int length=strlen(in);
for(int i=1;i<length;i++)
{
int x=out[i-1];
while(in[x+1]!=in[i] && x!=-1)
{
x=out[x];
}
if(in[x+1]!=in[i])
{
out[i]=-1;
}
else
{
out[i]=x+1;
}
}
}
void print1(char*a)
{
int n=strlen(a);
for(int i=0;i<n;i++)
{
cout<<a[i]<<'\t';
}
cout<<endl;
}
void print2(int*p,int length)
{
for(int i=0;i<length;i++)
{
cout<<p[i]<<'\t';
}
cout<<endl;
}
int kmp(char*text,char*pattern,int *p)
{
int text_len=strlen(text);
int j=0;
for(int i=0;i<text_len;)
{
while(pattern[j]!=text[i]&&j!=0)
{
j=p[j-1]+1;
}
if(pattern[j]==text[i])
{
if(j==strlen(pattern)-1)
{
return i-j;
break;
}
i++;
j++;
}
else
{
i++;
j=0;
}
}
return -1;
}
int main()
{
time_t t=time(NULL);
//srand(t);
produce_p(p,pattern);
print1(pattern);
print2(p,strlen(pattern));
for(int j=0;j<1000;j++)
{
int temp;
temp=produce_text(text,100,pattern);
cout<<text<<endl;
int x=kmp(text,pattern,p);
cout<<x<<endl;
for(int i=0;i<strlen(pattern);i++)
{
cout<<text[i+x];
assert(text[i+x]==pattern[i]);
}
assert(x<=temp);
cout<<endl;
}
system("pause");
return 0;
}
上面的代码可能有问题,懒得看了,下面是更新的版本,对应leetcode 28题 Implement strStr() :
#include<string>
#include<cassert>
#include<vector>
using namespace std;
class Solution {
vector<int> next;
void initnext(string needle)
{
int n=needle.size();
int i=1;
int j=0;
next.clear();
next.push_back(-1);
while(i<n)
{
if(needle[i]==0)
{
break;
}
if(needle[i]==needle[j])
{
if(j==0)
{
next.push_back(-1);
}
else
{
next.push_back(0);
}
i++;
j++;
}
else
{
if(next[j]!=-1)
{
next.push_back(j);
while(j!=-1&&needle[j]!=needle[i])
{
j=next[j];
}
if(j==-1)
{
i++;
j=0;
}
else
{
i++;
j++;
}
}
else
{
next.push_back(j);
i++;
j=0;
}
}
}
}
public:
int strStr(string haystack, string needle) {
int i=0;
int j=0;
int n=haystack.size();
initnext(needle);
while(i<=n)
{
if(needle[j]==0)
{
return i-needle.size();
}
if(haystack[i]==0)
{
return -1;
}
if(haystack[i]==needle[j])
{
i++;
j++;
}
else if(next[j]!=-1)
{
j=next[j];
}
else
{
i++;
j=0;
}
}
assert(0);
return -1;
}
};