Sweety

Practice makes perfect

导航

再解 KMP(初学)

Posted on 2014-08-10 23:14  蓝空  阅读(168)  评论(0编辑  收藏  举报

 SDIBT 2696   KMP模式匹配 一(串)

 

Description

求子串的next值,用next数组存放,全部输出

Input

输入一个字符串

Output

输出所有next值

Sample Input

abaabcac

Sample Output

0 1 1 2 2 3 1 2

 

#include<cstring>
#include<iostream>
using namespace std;
int main ()
{
	int next[2000];
	char p[2000];
    int j,k;
    next[0]=-1;
    j=0;
    k=-1;
	cin>>p;
	int	len=strlen(p);
    while(j<len-1){
        if(k==-1||p[j]==p[k]){   //匹配的情况下,p[j]==p[k]
            j++;
            k++;
            next[j]=k;
        }
        else                   //p[j]!=p[k]
            k=next[k];
    }
	int i;
	for(i=0;i<len-1;i++)
		cout<<next[i]+1<<' ';
	cout<<next[i]+1;
	return 0;
}

next数组产生过程辅助理解:

#include<cstring>
#include<iostream>
using namespace std;
int main ()
{
	while(1){
	int next[2000];
	char p[2000];
    int j,k;
    next[0]=-1;
    j=0;
    k=-1;
    cout<<"输入为:"; 
	cin>>p;
	int	len=strlen(p);
	cout<<endl<<"执行过程:"<<endl; 
    while(j<len-1)//len-1是因为后面有个j++ 
    {
        if(k==-1||p[j]==p[k])    //匹配的情况下,p[j]==p[k]
        {
        	cout<<"进入if语句:"<<endl;
            j++;  //递推因子只在这里加 
            cout<<"j++="<<j<<endl; 
            k++;
            cout<<"k++="<<k<<endl; 
            next[j]=k;
            cout<<"next["<<j<<"]="<<k<<endl<<endl;
        }
        else {          //p[j]!=p[k]
         cout<<"进入else语句:"<<endl;
		 int temp=k;                
            k=next[k];
            cout<<"k="<<next[temp]<<endl<<endl; 
			}
    }
    cout<<"获得的next数组为:"<<endl;
	int i;
	for(i=0;i<len-1;i++) //len-1是因为后面有个 
		cout<<next[i]<<' ';
	cout<<next[i]<<endl;
		} 
	return 0;
}

运行情况:

 

 

最后实例结合:http://blog.csdn.net/u014665013/article/details/38985621  


SDIBT 2697  KMP模式匹配 二(串)

Description

输入一个主串和一个子串,用KMP进行匹配,问进行几趟匹配才成功,若没成功,则输出0

Input

输入一个主串和一个子串

Output

匹配的趟数

Sample Input

ababcabcacbab
abcac

Sample Output

3

 

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int maxsize=100;
void getnext(string t,int next[])//此处也可以将int next[]改写成  int* next[]
{
	int j,k;
	j=0; k=-1; next[0]=-1;
	while(j<t.length()-1){
		if(k==-1 ||t[j]==t[k]){
			j++;k++;
			next[j]=k;
		}
		else k=next[k];
	}
}
int kmpindex(string s,string t)//s为目标串(主串),t为模式串
{
	int next[maxsize],i=0,j=0;
	//memset(next,-1,sizeof(next));
	getnext(t,next);
	int m=0;
	m++;
	int s_len=s.length(),t_len=t.length();//此处注意返回值得问题,详见:<a target=_blank href="http://blog.csdn.net/u014665013/article/details/38292717">http://blog.csdn.net/u014665013/article/details/38292717</a>
	while(i<s_len && j<t_len){	
		if(j==-1 ||s[i]==t[j]){
			i++;
			j++;
		}
		else
		 j=next[j],m++;
	}

	if(j>=int(t.length() ))
       		return m;
	else
		return 0;
}

int main()
{
	string a;
	string b;
	cin>>a;
	cin>>b;
	cout<<kmpindex(a,b)<<endl;

	return 0;
}


 

SDIBT 2698  KMP模式匹配 三(串)

 

Description

输入一个主串和一个子串,若匹配成功,则找出匹配的趟数和在子串在主串中的位置,若匹配不成功,则输出0

Input

输入两个字符串

Output

输出匹配的趟数和位置

Sample Input

ababcabcacbab
abcac

Sample Output

3 6

 

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int maxsize=100;
void getnext(string t,int next[])
{
	int j,k;
	j=0; k=-1; next[0]=-1;
	while(j<t.length()-1){
		if(k==-1 ||t[j]==t[k]){
			j++;k++;
			next[j]=k;
		}
		else k=next[k];
	}
}
void kmpindex(string s,string t)
{
	int next[maxsize],i=0,j=0;
	memset(next,-1,sizeof(next));
	getnext(t,next);
	int m=0;
	m++;
	while(i<s.length() &&j<int(t.length())){		
		if(j==-1 ||s[i]==t[j]){
			i++;
			j++;
		}
		else j=next[j],m++;
	}

	if(j>=int(t.length() ))
       		cout<<m<<' '<<(i-t.length())+1<<endl;;
	else
		cout<<0<<endl;
}

int main()
{
	string a;
	string b;
	cin>>a;
	cin>>b;
	kmpindex(a,b);

	return 0;
}