KMP


好吧,我是第一次手写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;
    }
};


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值