• C++编程练习(7)----“KMP模式匹配算法“字符串匹配


    子串在主串中的定位操作通常称做串的模式匹配。

    KMP模式匹配算法实现:
    /* Index_KMP.h头文件 */
    #include<string>
    #include<sstream>
    
    void get_next(std::string T,int *next)
    {
    	unsigned int i,j;
    	i=1;
    	j=0;
    	next[1]=0;
    	while(i<(T.size()-1))	/* 此处T的首个字符T[0]表示串T的长度,不参与计算 */
    	{
    		if(j==0||T[i]==T[j])	/* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
    		{
    			++i;
    			++j;
    			next[i]=j;
    		}
    		else
    			j=next[j];		/* 若字符不相同,则j值回溯 */
    	}
    }
    
    int Index_KMP(std::string S, std::string T, unsigned int pos)
    {
    	std::string s,t;				/*在字符串S,T的最前插入一个字符来保存串的长度值,*/
    	std::ostringstream s1,s2;		/*用来保证字符串的有用元素是从下标1开始*/
    	s1<<S.size()<<S;				/*将新的数组保存为s,t*/
    	s2<<T.size()<<T;
    	s=s1.str();
    	t=s2.str();
    	unsigned int i=pos;	/* i用于主串s当前位置下标值,若pos不为1,则从pos位置开始匹配 */
    	unsigned int j=1;	/* j用于字串t中当前位置下标值 */
    	int next[255];	/* 定义一next数组 */
    	get_next(t,next);	/* 对串t作分析,得到next数组 */
    	while (i<=(s.size()-1) && j<=(t.size()-1))	/* 若i小于S的长度且j小于T的长度时,循环继续 */
    	{
    		if ( j==0 || s[i]==t[j])	/* 两字母相等则继续,相对于朴素算法增加了j=0判断 */
    		{
    			++i;
    			++j;
    		}
    		else		/* 指针后退重新开始匹配 */
    		{
    			j=next[j];		/* j退回合适的位置,i值不变 */
    		}
    	}
    	if ( j>(t.size()-1) )
    		return i-(t.size()-1);
    	else
    		return 0;
    }

    KMP模式匹配算法的改进:

    /* Index_KMP.h头文件 */
    #include<string>
    #include<sstream>
    
    void get_nextval(std::string T,int *nextval)
    {
    	unsigned int i,j;
    	i=1;
    	j=0;
    	nextval[1]=0;
    	while(i<(T.size()-1))	/* 此处T的首个字符T[0]表示串T的长度,不参与计算 */
    	{
    		if(j==0||T[i]==T[j])	/* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
    		{
    			++i;
    			++j;
    			if (T[i]!=T[j])			/*若当前字符与前缀字符不同*/
    				nextval[i]=j;		/*则当前的j为nextval在i位置的值*/
    			else
    				nextval[i]=nextval[j];	/*如果与前缀字符相同,则将前缀字符的nextval值赋值给nextval在i位置的值*/
    			
    		}
    		else
    			j=nextval[j];		/* 若字符不相同,则j值回溯 */
    	}
    }
    
    int Index_KMP(std::string S, std::string T, unsigned int pos)
    {
    	std::string s,t;				/*在字符串S,T的最前插入一个字符来保存串的长度值,*/
    	std::ostringstream s1,s2;		/*用来保证字符串的有用元素是从下标1开始*/
    	s1<<S.size()<<S;				/*将新的数组保存为s,t*/
    	s2<<T.size()<<T;
    	s=s1.str();
    	t=s2.str();
    	unsigned int i=pos;	/* i用于主串s当前位置下标值,若pos不为1,则从pos位置开始匹配 */
    	unsigned int j=1;	/* j用于字串t中当前位置下标值 */
    	int next[255];	/* 定义一next数组 */
    	get_nextval(t,next);
    	while (i<=(s.size()-1) && j<=(t.size()-1))	/* 若i小于S的长度且j小于T的长度时,循环继续 */
    	{
    		if ( j==0 || s[i]==t[j])	/* 两字母相等则继续,相对于朴素算法增加了j=0判断 */
    		{
    			++i;
    			++j;
    		}
    		else		/* 指针后退重新开始匹配 */
    		{
    			j=next[j];		/* j退回合适的位置,i值不变 */
    		}
    	}
    	if ( j>(t.size()-1) )
    		return i-(t.size()-1);
    	else
    		return 0;
    }
    

    匹配算法不做变化,只需要将"get_next(T,next)"改为“get_nextval (T,next)”即可。

    总结:改进过的KMP算法,它是在计算出 next 值的同时,如果a位字符与它 next 值指向的 b 位字符相等,则该 a 位的nextval 就指向 b 位的 nextval 值,如果不等,则该 a 位的 nextval 值就是它自己 a 位的 nextval 的值。
  • 相关阅读:
    生产者消费者模式
    Linux提权(capabilities)
    协程
    xpath常用
    iframe 练习
    python 实现数据库中数据添加、查询与更新
    web网站压力/性能测试经验分享
    AttributeError: module 'applescript' has no attribute 'app'解决方案
    pip3: error: can't exec '/usr/local/bin/pip3' (errno=No such file or directory)报错解决方案
    看了这篇双十一抢购攻略?喜欢的东西还能抢不到?
  • 原文地址:https://www.cnblogs.com/fengty90/p/3768856.html
Copyright © 2020-2023  润新知