重学数据结构:串的匹配算法(C语言)

朴素模式匹配算法

  1. 算法描述:定位操作。若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置;否则函数值为0。
  2. 算法思想:就是把比較主串字符串一位一位地跟模式字符串相比,比较简单粗暴。
  3. 算法缺点:当某些子串与模式串能部分匹配时,主串的扫描指针 i 经常回溯,导致时间开销增加
//朴素匹配算法
int SimpleIndex(String S,String T)
{
   int result=-1;
   int i=1,j=1,k=1;
   while(i<S.length&&j<T.length)
   {
	   if(S.data[i]==T.data[j])
	   {
	       i++;
		   j++;
	   }
	   else
	   {
		  k++;
		  i=k;
	      j=1;
	   }
   }
   if(j>=T.length) //如果找到,则输出找到位置
	   result=k;
   return result; 
}

测试代码

	String S,T;
	InitString(&S);
	InitString(&T);
	StrAssign(&S,"wangdao");
	printf("输出比较字符串S:");
    PrintString(S);
	StrAssign(&T,"dao");
	printf("输出模式字符串T:");
    PrintString(T);

	int result=SimpleIndex(S,T);
    printf("SimpleIndex(S,T):%d\n",result);
    return 0;

测试结果

输出比较字符串S:wangdao
输出模式字符串T:dao
SimpleIndex(S,T):5

KMP算法

  1. 算法描述:由D.E.Knuth,J.H.Morris和V.R.Pratt提出,因此称为 KMP算法。在朴素匹配算法的基础上,为了减少主串指针I的回溯。
  2. 算法代码:
//KMP算法
int Index_KMP(String S,String T,int next[])
{
    int i=1,j=1;
	while(i<S.length&&j<T.length)
	{
		int s_value=S.data[i];
		int t_value=T.data[j];
		if(j==0||s_value==t_value)
		{
		   i++;
		   j++;
		}
		else
		{
		    j=next[j];
		}
	}
	if(j>=T.length)
		return i-T.length;
	else
	    return -1;
}

求模式串的Next数组

void GetKMP_NextArr(String S,int next[])
{
    next[1]=0;
    int j=0,i=1;
	while(i<S.length)
	{
		if(j==0||S.data[i]==S.data[j])
		{
		   i++;j++;
		   next[i]=j;
		   //printf("next[%d]=%d\n",i,j);
		}else
		{
		   //printf("%d=next[%d]\n",next[j],j);
		   j=next[j];
		  
		}
	}
	
}

测试代码

	String S,T,V;
	InitString(&S);
	InitString(&T);
	
	StrAssign(&S,"aaaacaaaabeccdd");
	StrAssign(&T,"aaaab");

    int next[6];
	GetKMP_NextArr(T,next);
	PrintNextArr(next,6);
    
	int result_index=Index_KMP(S,T,next);
	printf("Index_KMP(S,T,next)=%d\n",result_index);

测试结果

---next数组输出开始----
0       1       2       3       4
---next数组输出结束----
原字符串:aaaacaaaabeccdd
匹配字符串:aaaab
Index_KMP(S,T,next)=5
Press any key to continue

KMP算法优化

KMP在朴素算法上的改进已经优化了主字符串回溯的问题,但是对于已知匹配字符串的情况下,可以对字符串的索引提前预判,从而达到性能更优的效果。
其实一般情况下,nextval数组和next数组是相等的。但是在极端的情况下,nextval可以比next少对比几次,从而提升执行效率。如以下情况:

index12345
匹配字符串aaaab
next01234
nextval00004

以上这种情况可以少对比4次,可以这样理解:nextval优化的方法主要针对匹配字符串的重复元素的无意义对比。

求模式串的NextVal数组

void GetKMP_NextValArr(String S,int nextval[])
{
    nextval[1]=0;
    int j=0,i=1;
	while(i<S.length)
	{
		if(j==0||S.data[i]==S.data[j])
		{
		   i++;j++;
		   if(S.data[i]!=S.data[j])
			   nextval[i]=j;
		   else
			   nextval[i]=nextval[j];
		}else
		{
		   j=nextval[j];
		  
		}
	}
}

测试代码

	String S,T;
	InitString(&S);
	InitString(&T);
	
	StrAssign(&S,"aaaacaaaabeccdd");
	StrAssign(&T,"aaaab");

    int next[6];
	GetKMP_NextValArr(T,next);
    
	int result_index=Index_KMP(S,T,next);
	printf("Index_KMP(S,T,next)=%d\n",result_index);

测试结果

Index_KMP(S,T,next)=5
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值