zoukankan      html  css  js  c++  java
  • 串:KMP算法

    KMP算法第一次看起来稍微有点复杂,其实原理还是很简单的,想清楚就理解了。

    举个简单的栗子:

    主串s:abcabfd

    模式串t:abcabe

    如果使用比较原始的方法,一个个字符进行比较,当进行到主串的i=5,s[5]=f的位置,发现与j=5,t[5]=e不匹配,则只能重新从i=2开始,与j=1再进行匹配。

    而实际上,由于模式串的特点:abcabe,这个串里有两个ab,而主串f前也有个ab,则我们可以直接将f与j=3,t[3]=c进行对比,因为前面的ab是一样的,不用多一次比较了。

    所以KMP算法实际上就是利用了模式串的特点,如果模式串中有较大的重复,则可以省略很多的判断,因为在主串中i是至少不动的,不用像原始的算法那样回溯。

    KMP算法分为两个部分:

    1).KMP的主体

    2).next数组

    1)的作用就是对两个串进行模式匹配,但1)需要用到2)中的next数组,因此在进行匹配前先要构建出一个next数组。

    next数组的作用就类似于上面栗子中,当判断到s[5]与t[5]不相等时,直接查找next[5],next[5]指向的是f应该比较的下一个字符,这里next[5]=2,因为f前的ab与e前的ab是已知相等的,所以直接从t[2]互相对比就可以。

    next数组的构建:

    考虑模式串t,模式串的i与j位置:

    若t[i]=t[j],则可知(1~i)与(j-i+1~j)间完全相等,则对next[j+1],也就是当主串不与模式串的第j+1个字符相等时,应该对比的是第i个元素的下一个,也就是next[j+1]=i+1;

    若t[i]!=t[j],但可知(1~i-1)与(j-i+1~j-1)间完全相等,则对j个元素,应该首先与第next[j]个元素再对比一次,如果这个时候相等,则next[j+1]=next[j]+1;

    否则继续找下一个,也就是第next[next[j]]个元素。

    在得到next数组之后,剩下的KMP主体就很简单了,只要i与j对应的元素对比,如果s[i]==s[j],则i++,j++;否则则i与next[j]个元素对比......

    代码:

    可以看到,代码分了两部分:

    一部分为KMP主体,另一部分为next数组的创建。

    另外,对于next数组的创建中有这么一部分:

    他们的作用是:

    比如模式串为:aab

    创建next时,next[0]自然等于-1,而next[1],如果没有这部分,将被设置为0,也就是说如果主串与模式串的i=1部分不相等时,还会去找t[0]对比,而实际上t[0]与t[1]都是a,因此是没有必要的,应该直接设置为-1。

    if(t[i]!=t[j])
    	next[i]=j;
    else
    	next[i]=next[j];


    class Solution
    {
    public:
    	int KMP(string s,string t)
    	{
    		vector<int> next=get_next(t);
    		int i=0;int j=0;
    		while(i<s.size()&&j<t.size())
    		{
    			if(j==-1||s[i]==s[j])
    			{
    				i++;
    				j++;
    			}
    			else
    				j=next[j];
    		}
    		if(j<t.size())
    			return 0;
    		else
    			 return i;
    	}
    	vector<int> get_next(string t)
    	{
    		vector<int> next(t.size(),-1);
    		int i=0;int j=-1;
    		while(i<(t.size()-1))
    		{
    			if(j==-1||t[i]==t[j])
    			{
    				i++;
    				j++;
    				if(t[i]!=t[j])
    					next[i]=j;
    				else
    					next[i]=next[j];
    			}
    			else
    				j=next[j];
    		}
    		return next;
    	}
    };
    

      

  • 相关阅读:
    【代码整合】导航
    【代码片段】简易de幻灯片解说prevScene() & nextScene()方法
    PHP file函数技巧去除每个元素换行符,去除空行元素
    windows ldap 小例子
    VI 如何格式化代码
    php通过Active Directory简单验证LDAP
    linux系统监控常用命令
    使用wget 命令下载链接文件
    【转】关于sql的书写
    php数组合并:array_merge与 “+”
  • 原文地址:https://www.cnblogs.com/lxy-xf/p/11233420.html
Copyright © 2011-2022 走看看