zoukankan      html  css  js  c++  java
  • 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 的值。
  • 相关阅读:
    关于xampp 集成开发包电脑重启mysql无法启动的问题
    ThinkPhP html原样入库
    java 获取图片大小(尺寸)
    xampps 不能配置非安装目录虚拟主机解决方案
    从0开始 java 网站开发(jsp)【1】
    Hello world!
    SpringMVC归纳-1(model数据模型与重定向传参技术)
    TTL与非门电路分析
    git入门手册:git的基本安装,本地库管理,远程上传
    实现简单的评论区功能
  • 原文地址:https://www.cnblogs.com/fengty90/p/3768856.html
Copyright © 2011-2022 走看看