精华内容
下载资源
问答
  • 字符串模式匹配算法

    2011-10-14 15:53:05
    关于ACM竞赛字符串模式匹配算法及其改进思路
  • 用C++实现BM的字符串模式匹配算法,两个代码分别实现坏字符规则和好后缀规则
  • 算法案例分析—字符串模式匹配算法

    千次阅读 多人点赞 2020-09-09 19:49:13
    今天来和大家分享一个关于字符串比较的模式匹配算法,在数据结构中对字符串的相关操作中,对子串的定位操作通常称为串的模式匹配,同样他也是各种串处理中最重要的操作之一,同时子串也称为模式串,关于主串和模式串...

    目录

    一、朴素的模式匹配算法

    二、KMP算法(改进的模式匹配算法)


    hello!大家好哇,我是灰小猿,一个超会写bug的沙雕程序猿!

    今天来和大家分享一个关于字符串比较的模式匹配算法,在数据结构中对字符串的相关操作中,对子串的定位操作通常称为串的模式匹配,同样他也是各种串处理中最重要的操作之一,同时子串也称为模式串,关于主串和模式串的匹配算法常用的主要有两种:朴素的模式匹配算法和KMP算法(改进的模式匹配算法),接下来将分别对这两种算法进行分析。

    一、朴素的模式匹配算法

    朴素的模式匹配算法也被称为布鲁特—福斯算法,其基本思想是:从主串的第一个字符起与模式串的第一个字符相比较,若相等,则逐一对之后的字符进行比较,否则从主串的第二个字符与模式串的第一个字符重新比较,直到模式串中的每一个字符依次与主串中连续的字符序列相匹配为止,这时就称为匹配成功,如果不能在主串中找到与模式串相匹配的内容,则称为匹配失败。

    接下来举一个例子,以字符数组存储字符串,实现朴素的模式匹配算法。

    //传入主串s和模式串t,同时设定从主串中开始匹配的位置pos
    int index(char s[],char t[],int pos) {
    	int i,j,slen,tlen;
    	i = pos;
    	j = 0;
    	slen = s.length;	//获取到主串的长度
    	tlen = t.length;	//获取到模式串的长度
    	while (i<slen && j<tlen) {
    		if (s[i] == t[j]) {
    			i++;
    			j++;
    		}
    		else {
    			i = i-j+1;
    			j=0;
    		}		
    	}
    	if (j>=tlen) {
    		return i-tlen;
    	}
    	return 1;
    }

     

    二、KMP算法(改进的模式匹配算法)

    KMP算法是上一个算法的改进,相比于朴素的模式匹配算法,KMP算法在进行主串和模式串的匹配过程中,每当匹配过程中出现相比较的字符不相等时,不需要回退主串的字符位置指针,而是利用已经得到的“部分匹配”结果将模式串向右“滑动”尽可能远的距离,再继续进行比较。

    设模式串为“P0...P(m-1)”,KMP匹配算法的思想是:当模式串中的字符Pj与主串中相应的字符Si不相等时,因其前j个字符(“P0...P(j-1)”)已经获得了成功的匹配,所以若模式串中的“P0...P(k-1)”与“P(j-k)...P(j-1)”相同,这时可令P0与Si相比较,从而使i无需回退。

    在KMP算法中,依据模式串的next函数值可以实现子串的滑动,若令next[j]=k,则next[j]表示当模式串中的Pj与主串中相应的字符不相等时,令模式串的Pnext[j]与主串的相应字符进行比较,

    关于next函数有如下的定义:

    以下是求模式串的next函数的程序:

    //求模式串p的next函数值,并存入数组next中
    void Get_next(char *p,int next[])
    {
    	int i,j,slen;
    	slen = strlen(p);	//获取到模式串的长度
    	i=0;
    	while (i<slen) {
    		if (j==-1||p[i]==p[j]) {
    			++i;
    			++j;
    			next[i] = j;
    		} else {
    			j = next[j];
    		}
    	}
    }

    在获取到的next函数后,

    在KMP模式匹配算法中,设模式串的第一个字符下标为0,则KMP算法如下:

    /*利用模式串p的next函数,求p在主串s中从第pos个字符开始的位置*/
    /*若匹配成功,返回模式串在主串的位置下标,否则返回-1 */
    int Index_KMP(char *s,char *p,int pos,int next[])
    {
    	int i,j,slen,plen;
    	i=pos-1;
    	j=-1;
    	slen = strlen(s);	//求主串的长度
    	plen = strlen(p);	//求模式串的长度
    	while (i<slen && j<plen) {
    		if (j==-1||s[i]==p[j]) {
    			++i;
    			++j;
    		} else {
    			j=next[j];
    		}
    	}
    	if (j>=plen) {
    		return i-plen;
    	}
    	else {
    		return -1
    	}
    		
    }

    关于字符串模式匹配算法就分享到这里,有不足的地方还希望各位大佬一起指正,

    觉得不错记得点赞关注哟!

    大灰狼陪你一起进步!

    展开全文
  • KMP字符串模式匹配算法ppt,KMP算法是很精妙的算法,同时比较难懂。KMP字符串模式匹配算法ppt
  • KMP字符串模式匹配算法 当我们使用简单字符串模式匹配算法时,时间复杂度为O(n*m),这里n为目标串的长度,m为模式串的长度。在循环的过程中,有很多次匹配其实存在回溯,浪费了很多时间。可以根据模式串本身的性质...

    KMP字符串模式匹配算法

    当我们使用简单字符串模式匹配算法时,时间复杂度为O(n*m),这里n为目标串的长度,m为模式串的长度。在循环的过程中,有很多次匹配其实存在回溯,浪费了很多时间。可以根据模式串本身的性质来设计一个新的高效算法,即跳过肯定不匹配的循环,而直接从左边子串已经相同的位置开始比较,时间复杂度大大降低,该算法就是KMP字符串模式匹配算法。

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int KMPIndexHelp(const string &T,const string &P,int pos,int next[]){
        int i=pos,j=0;
        while(i<T.length() && j<P.length())
        {
            if(j==-1)
            {
            i++; j=0;
            }
            else if(T[i]==P[j]){
                i++; j++;
            }
            else
            {
                j=next[j];
            }
        }
    
        if(j<P.length()) return false;
        else return i-j;
    }
    
    void GetNext(const string &P,int next[])
    {
        next[0]=-1;
        int j=0,k=-1;
        while(j<P.length()-1)
        {
            if(k==-1)
            {
                next[j+1]=0;
                j++;k=0;
            }
            else if(P[k]==P[j])
            {
                next[j+1]=k+1;
                j++;k++;
            }
            else
            {
                k=next[k];
            }
        }
    }
    
    int KMPIndex(const string &T,const string &P,int pos=0){
       int *next=new int[P.length()];
       GetNext(P,next);
       int result=KMPIndexHelp(T,P,pos,next);
       delete []next;
       return result;
    }
    int main()
    {
        int r=0;
        string T="acabaabaabcacx";
        string P="abaabcac";
        cout << KMPIndex(T,P,r) <<endl;
        return 0;
    }
    
    
    展开全文
  • 字符串模式匹配算法的改进研究.pdf 字符串模式匹配算法的改进研究.pdf
  • KMP算法是字符串模式匹配算法中较为高效的算法之一,其在某次子串匹配母串失败时并未回溯母串的指针而是将子串的指针移动到相应的位置。书中详细描述了KMP算法,前面你已经计算了子串移动的next数组,现在就来利用该...

    题目描述

    KMP算法是字符串模式匹配算法中较为高效的算法之一,其在某次子串匹配母串失败时并未回溯母串的指针而是将子串的指针移动到相应的位置。书中详细描述了KMP算法,前面你已经计算了子串移动的next数组,现在就来利用该next数组来实现KMP模式匹配。
    输入

    3组字符串,每组字符串占一行。每行包含由空格分隔的两个字符串,字符串仅由英文小写字母组成且长度不大于100。
    输出
    每组数据输出1行,输出后一个字符串在前一个字符串中的位置,如果不匹配,则输出0。
    样例输入 Copy
    string str
    thisisalongstring isa
    nosubstring subt
    样例输出 Copy
    1
    5
    0

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    char a[105];
    char b[105];
    char next[105];
    int L1, L2;
    
    void f()
    {
            int i;
            next[0]=-1;
            int j=-1;
            for(i=1;i<strlen(a);i++)
            {
                while(j!=-1&&a[i]!=a[j+1])	j=next[j];
                
                if(a[i]==a[j+1])	j++;
                
                if(j==-1||a[i+1]!=a[j+1])	next[i]=j;
                else    next[i] = next[j];
    
            }
    }
    
    int KMP()
    {
        int i;
        int j = -1;
        f();
        for(i=0;i<L2;i++)
        {
            while(j!=-1&&b[i]!=a[j+1])	j=next[j];
            
            if(b[i] == a[j+1])   j++;
            
            if(j == L1-1)	return i+1-L1;
        }
        return -1;
    }
    
    int main()
    {
        int  i, j, x, k = 3;
        while(k--)
        {
            scanf("%s %s", b, a);
            L1=strlen(a);
            L2=strlen(b);
            x=KMP();
            printf("%d\n", x+1);
        }
        return 0;
    }
    
    
    展开全文
  • KMP字符串模式匹配算法,内是ppt讲解,比较通俗易懂了。。
  • 字符串模式匹配:在一个文本(长字符串)中找出一个或多个指定的字符串(Pattern),并返回其位置。...下面介绍几种字符串模式匹配算法:Brute-Force算法、KMP算法、BM算法、Sunday算法 第一种算法:BF算法(暴力)


    参考文章:July 的从头到尾彻底理解KMP


    字符串模式匹配:在一个文本(长字符串)中找出一个或多个指定的字符串(Pattern),并返回其位置。


    下面介绍几种字符串模式匹配算法:Brute-Force算法、KMP算法、BM算法、Sunday算法

    文本字符串S,索引 i ,模式字符串P,索引 j

    字符串匹配算法之BF算法:

        基本思路:假设文本串S比较到i位置,模式串P比较到j位置。

                         如果当前字符匹配成功(S[i] == P[j]),那么继续向下比较,i ++,j++。

                         如果当前字符匹配失败(S[i] != P[j]),那么将文本串的索引 i ,回溯到 i - j +1位置(回到模式串开头对应的文本串的位置的下一个位置,就是将模式串相对于文本串右移1位),然后 模式串的索引 归0,即:i = i - j +1;j=0。

      如果文本串的长度为n,模式串的长度为m,那么BF的时间复杂度为O(m *n)。

    代码:

    /*
    	 * BF算法:暴力匹配
    	 * 
    	 */
    	
    	public static int BFSearch(String s,String p){
    		char[] ss = new char[s.length()];
    		char[] pp = new char[p.length()];
    		s.getChars(0, s.length(), ss, 0);
    		p.getChars(0, p.length(), pp, 0);
    		return BFSearch(ss,pp);
    		
    	}
    	
    	/**
    	 * BF算法的具体实现:
    	 * 
    	 * @param s 文本串
    
     * @param p 模式串
    	 * @return 如果搜索成功,返回p在s中的索引,否则返回 -1;
    	 */
    
    	private static int BFSearch(char[] s, char[] p) {
    		int i = 0;
    		int j =0;
    		while(i<s.length && j <p.length){
    			if(s[i] == p[j]){
                                //如果当前字符匹配成功,则继续匹配下一个
                                   i++;
    				j++;
    			}else{
                              // 如果当前字符匹配失败,则将文本串索引回掉置i-j+1位置,j = 0;
                              //相当于模式串向右移动一位,从模式串开始字符再进行比较。
                                   i = i-j+1;
    				j =0;
    			}
    		}
    		if(j<p.length){
    			return -1;
    		}else{
    			return i-j;
    		}
    	
    	}
    

    字符串匹配算法之KMP算法:

       算法的基本流程:

              假设现在文本串S匹配到 i 位置,模式串匹配到 j 位置。

              如果 j = -1,或者当前字符匹配成功(即 S[ i ] == P[ j ]),则继续向下匹配,i ++, j ++.

              如果  j != -1, 并且当前字符匹配失败(即S[ i ]  != P[ j ] ),则保持文本串的索引 i 的位置不变, j =next [ j ]。

          相当于模式串相对与文本串右移 j - next [ j ] 位。

    即:当匹配失败时,模式串向右移动的位数 = 失配字符所在位置 - 失配字符对应的next值,即 移动的位数 = j - next[ j ]。


    关于next 数组的求解后面叙述。

    代码:

    	public static int KMPSearch(String s,String p){
    		
    		char[] ss = new char[s.length()];
    		char[] pp = new char[p.length()];
    		s.getChars(0, s.length(), ss, 0);
    		p.getChars(0, p.length(), pp, 0);
    		return KMPSearch(ss,pp);
    		
    		
    	}
    /**
     * KMP算法具体实现
     * @param s 文本串
     * @param p 模式串
     * @return
     */
    	private static int KMPSearch(char[] s, char[] p) {
    		int slen = s.length;
    		int plen = p.length;
    		int i = -1;//文本串索引
    		int j = -1;//模式串索引
    		int[] next = getNext(p);//next 数组
    		while(i <slen && j<plen){
    			if(j == -1 || s[i] == p[j]){
    				//如果 j = -1 或者 s[i] == p[j](当前字符匹配成功),则继续向下匹配
    				i++;
    				j++;
    			}else{
    				//如果 j != -1 并且s[i] != p[j](当前字符匹配失败),则保持文本串的索引位置不变,令 j = next[j],
    				//相当于模式串右移 j-next[j]个位置。
    				
    				j = next[j];
    			}			
    		}
    		if(j < plen){
    			return -1;
    		}else{
    			return i - plen;
    		}
    		
    	}

    下面叙述next数组的求解方法:

    第一种: 先寻找前缀后缀最长公共元素的长度,然后将上一步求的数值整体向右移动一位,就是next 数组从1 ~ plen-1所对应的值,next[0] = -1.

    第二种:代码递推求的。已知 next[0] = -1,并且next[ j ] = k,然后递推求解 next[ j +1] = ?

    代码:

    /*
     * 计算模式串P的next数组,并且规定:
     * next[0] = -1;
     * 注意:next[j] = k :表示的是pj之前的字符串的前后缀具有长度为k 的公共子序列
     */
    	private static int[] getNext(char[] p) {
    		
    		int plen = p.length;
    		int[] next = new int[plen];
    		int k = -1;//前缀索引
    		int j = 0;//后缀索引
    		next[0] = -1;
    		while(j < plen-1){ 
    			if(k == -1 || p[k] == p[j]){
    				k++;
    				j++;
    				/*
    				 * 原始的next 数组求法只有下面一行: next[j] = k;不存在if else 
    				 */
    				//next[j] =k;
    			/*
    			 * 对next数组进行了优化,
    			 * p[j]失配时,若p[j] == p[next[j]],则	p[next[j]]必然也会失配。所以为了避免这种情况,
    			
    			 */
    				//p[k]表示前缀,p[j]表示后缀
    				if(p[k] != p[j]){
    					next[j] = k;
    				}else{
    				
    					next[j] = next[k];//若p[k] == p[j],(p[j]在p[k]后面,也就是next[j]是要靠next[k]递推而来的),
    					//那么当p[j]与s[i]发生失配时,根据KMP算法,会将p[next[j]] 与s[i]进行相等比较,由于已知若p[j] == p[k](next[j] = k),
    					//那么p[k]必定与s[i]失配,所以为了避免此操作,在获得next[j]时,不应该将k赋值给它,而应该将next[k]赋给next[j],若p[next[k]]还等于p[j],
    					//那么就继续重复上述操作,直到k == -1 || p[k] != p[j]为止。
    				}
    				
    			}else{
    				k = next[k];
    			}
    		}
    		
    		
    		return next;
    	}
    	

    关于字符串的前缀后缀最长公共序列的长度与next 数组的关系:


    假设模式字符串为: P0,P1,P2,。。。,Pj-1,Pj

    (1)字符串的前缀后缀最长公共序列的长度:

           对于上述模式字符串,若存在   P0,P1,P2 ...Pk-1,Pk = Pj-k,Pj-k+1,....,Pj-1,Pj ,那么在包含Pj 的模式字符串P有最大长度为k+1的相同前缀后缀。

    (2)求next 数组

          next[ j] = k,表示的当前模式串P中P[j]之前的字符串(即P0 ....Pj-1)有最大长度为k 的前缀后缀公共序列。

    所以:将(1)求的数值整体后移一位,就是对应的next数组的值,并规定next[0] = -1.

          如果文本串的长度为n,模式串的长度为m,那么匹配过程的时间复杂度为O(n),算上计算next的O(m)时间,KMP的整体时间复杂度为O(m + n)。

    字符串匹配算法之BM算法:

          KMP算法的匹配是从模式串的开头就开始匹配的,BM算法是从模式串的尾部开始匹配的,最坏时间复杂度为O(n),

    在实践中,比KMP算法的效率高。

    BM算法中有两个规则:

        坏字符规则:当文本串中的某个字符与模式串中 的某个字符不匹配时,文本中的该字符就称为坏字符。此时模式串需要向右移动,移动的位数 = 坏字符在模式串中的位置 - 坏字符在模式串中最右出现的位置。此外,如果"坏字符"不包含在模式串之中,则最右出现位置为-1。

       好后缀规则:当字符失配时,后移位数 = 好后缀在模式串中的位置 - 好后缀在模式串上一次出现的位置,且如果好后缀在模式串中没有再次出现,则为-1。


    字符串匹配算法之Sunday算法

    Sunday 算法何BM算法很相似,BM算法是从后往前匹配,Sunday算法是从前往后匹配,并且失配的时候关注的是文本串中参加匹配的最末尾的字符的下一位字符。

                如果该字符没有在模式串中出现,则直接跳过,即移动的位数 = 匹配串的长度+1;

              否则,移动的位数 = 模式串中最右端的该字符到末尾的距离 +1.   

    举例:

            文本串:  substring searching algorithm

              模式串: search

    (1)开始时,把模式串与文本串对其,从文本串的开头进行匹配,匹配第一个字符S,S匹配成功,继续下一个

                          substring searching algorithm

                           search

        (2)第二个字符 u,与e 不匹配,失配时关注的是文本串中参与匹配的最末尾字符的下一位字符,即i  ,查找i 在模式串中最靠右的位置,模式串中没有i,那么模式串要移动的位数 =  模式串的长度 +1 = 6 +1 = 7;所以模式串右移7位,移动到 与 i 的下一位 n 对其的位置。

                         substring searching algorithm

                         search

                         substring searching algorithm

                                          search

    (3)然后从n 开始重新匹配,此时第一个字符 n就不匹配,所以关注文本串中参与匹配的最末尾的字符的下一个字符 : r,r 在模式串中的最靠右的位置到末端字符的距离是2,所以模式串要右移的位数 = 模式串中最右端的该字符到末尾的距离 +12 +1 = 3.是两个r对其

                     substring searching algorithm

                                                   search


    (4)匹配成功。












    de

    展开全文
  • 关于KMP_字符串模式匹配算法的教学课件,详细讲解了Kmp 的原理与不足和改进
  • 提供了一种新的字符串模式匹配算法的实现,而常规算法往往低效.字符串模式匹配算法是程序开发过程中应用非常广的重要算法.
  • HDUOJ 1634 算法4-6:KMP字符串模式匹配算法实现 题目链接 题目描述 KMP算法是字符串模式匹配算法中较为高效的算法之一,其在某次子串匹配母串失败时并未回溯母串的指针而是将子串的指针移动到相应的位置。严蔚敏...
  • 1,问题描述 字符串模式匹配:串的模式匹配 ,是求第一个字符串(模式串:str2)在第二个字符串(主串:str1)中的起始位置。 注意区分: 子串:要求连续 (如:abc ...简单字符串模式匹配算法,也就是了BF(Brut...
  • 数据结构 基于字符串模式匹配算法的病毒感染检测问题实验目的实验内容实验提示 实验目的 1.掌握字符串的顺序存储表示方法。 2.掌握字符串模式匹配算法BF算法或KMP算法的实现。 实验内容 问题描述 医学研究者最近发现...
  • 《数据结构(C语言版 第2版)》严蔚敏 实验四 基于字符串模式匹配算法的病毒感染检测问题,含实验报告
  • 实验四 基于字符串模式匹配算法的病毒感染检测 【实验目的】 1.掌握字符串的顺序存储表示方法。 2.掌握字符串模式匹配BF算法和KMP算法的实现。 【实验内容】 问题描述 医学研究者最近发现了某些新病毒,通过对这些...
  • 改进的字符串模式匹配算法——KMP操作前言一、一般的模式匹配算法二、KMP算法的基本思想1.一般方法的弊端2.解决想法3.数学解释4.next()详解(1)解剖next()函数总结 前言 关于什么是CMP操作,详情见 KMP算法 一...
  • 字符串模式匹配:求一个字符串(模式串)在另一个字符串(主串)中的位置,称为字符串模式匹配 KMP算法时间复杂度:O(n+m) 核心思想:当一趟匹配过程中出现字符不匹配时,不需要回溯主串的指针,而是利用已经得到...
  • 朴素模式匹配算法的基本思想: 对主的每一个字符作为子串开头,与模式进行匹配。对主做大循环,每个字符开头做模式长度的小循环,直到匹配成功或全部遍历完成为止。 代码实现非常简单: int ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,282
精华内容 2,512
关键字:

字符串模式匹配算法