算法:字符串匹配、BF/KMP/近似匹配

#include<iostream>
#include<cstring>

using namespace std;

#define MAXSTR 100

//----------------BF---------------- 时间o(n*m)
int StringMatch_BF(char *str, char *pat)  //O(M*N) M=|str| , N=|pat|
{	
	if(str==NULL||pat==NULL) return -1;
	
	int i=0,j=0,irec=0;
	
	for(;;){
		while(str[i]!='\0'&&pat[j]!='\0')
			if(str[i]==pat[j]){
				i++;
				j++;
			}
     		else{
				i=++irec;
				j=0;
				break;
			}
		if(pat[j]=='\0') //找到匹配位置 
			return irec;
		if(str[i]=='\0') //没有匹配位置 
			return -1;			
	}
     		
}
//----------------BF---------------- 



//------------KMP-------------预处理子串,得到next数组,表示子串中的某个位置在跟主串不匹配时,应该继续跟主串匹配的下一个位置。
//时间o(n+m)摊还分析
void NextInit(int next[], char* pat)
{
	next[0]=-1;
	if(pat[1]=='\0')
		return;
	next[1]=0;
	int pos=2,cnt=0;
	
	while(pat[pos]!='\0'){
		if(pat[pos-1]==pat[cnt]){
			next[pos++]=++cnt;
		}
		else{
			if(cnt>0)
				cnt=next[cnt];
			else
				next[pos++]=0; //此时cnt==0 
		}
	}
	
	for(pos=1;pat[pos]!='\0';pos++) //改进next数组
		if(pat[pos]==pat[next[pos]])//这种情况下可以直接重新开了
			next[pos]=0; //如主串cbdcbc和cbdcbd不匹配时,要拿子串的开头c和主串的结尾c比较
}


int StringMatch_KMP(char *str, char *pat)
{
	int next[MAXSTR];
	NextInit(next,pat);
	
	int i=0,j=0,irec=0;
	
	while(str[i]!='\0'&&pat[j]!='\0')
		if(str[i]!=pat[j]){
			if(next[j]<0){
				i++;
				irec=i;
				j=0;
			}
			else{
				irec+=j-next[j];//原串的匹配初始位置也发生了变化 
				j=next[j];  
			}
		}
		else{
			i++;
			j++;
		}	
		
		
	if(pat[j]=='\0')
		return irec;
	else
		return -1;
					
}
//---------------KMP----------------------


//---------------其他匹配算法待补充,如后缀数组,自动机等----------------------


//------------字符串近似匹配-------------
int StringNearMatch(char *str, char*pat,int k,int &begin)
{
	int EditDis[MAXSTR][MAXSTR];
	int rec[MAXSTR][MAXSTR];
	int i,j;
	EditDis[0][0]=0;
	for(i=0;str[i]!='\0';i++)
		EditDis[i+1][0]=0;
	for(i=0;pat[i]!='\0';i++)	
		EditDis[0][i+1]=i+1;
		
	for(i=0;str[i]!='\0';i++)
		for(j=0;pat[j]!='\0';j++)
			if(str[i]==pat[j]){
				EditDis[i+1][j+1]=EditDis[i][j];
				rec[i+1][j+1]=0;
			}
			else
				if(EditDis[i][j]>EditDis[i][j+1]){
					EditDis[i+1][j+1]=EditDis[i][j+1]+1;
					rec[i+1][j+1]=-1;
				}
				else{
					if(EditDis[i][j]>EditDis[i+1][j]){
					EditDis[i+1][j+1]=EditDis[i+1][j]+1;
					rec[i+1][j+1]=1;
					}
					else{
						EditDis[i+1][j+1]=EditDis[i][j]+1;
						rec[i+1][j+1]=0;
					}
				}

//下面是找到第一个匹配模式串的地方,并返回末尾位置	,begin返回初始位置
	if(EditDis[0][j]<=k){//错误次数允许大于等于模式串的长度 
		begin = -1;
		return -1; 
	}
	
	for(i=0;str[i]!='\0';i++)
		if(EditDis[i+1][j]<=k)
			break;
	if(str[i]=='\0') //找不到近似匹配的子串 
		return -2;
	
	int tail=i; 
	i++;
	while(i>0&&j>0&&EditDis[i][j]!=0)
		switch(rec[i][j]){
			case 0: i--;j--;break;
			case -1: i--;break;
			case 1: j--;break;
		}
		
	while(j!=0){ i--;j--; }
	
	begin=i>=0?i:-1;//-1表明要在的前面加字符串才可 
	return tail;	
			
	
}
//------------字符串近似匹配-----------------
 

int main()
{
	
loop:
	char str1[MAXSTR],str2[MAXSTR];
	cin>>str1>>str2;
	//cout<<StringMatch_BF(str1,str2)<<endl;	
	//cout<<StringMatch_KMP(str1,str2)<<endl;
	
	int begin,k;
	cin>>k;
	int tail=StringNearMatch(str1,str2,k,begin);
	if(tail==-2){
		cout<<"not find"<<endl;
		goto loop; 
	}
	cout<<begin<<" , "<<tail<<endl;
	
goto loop;
	
	return 0;	
} 


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值