• KMP算法实现


    下面是一个C代码实现的KMP算法,算法最困难的地方是计算出next数组,里面记录了匹配字符串各个位上的值。这个值可以叫做“部分匹配值”或“覆盖率”。

    要理解KMP算法首先要知道“朴素字符串匹配”算法,就是从头到尾比较字符,如果相等就同时后移,如果不相等则源字符串的搜索位置后移一位,然后重新匹配一遍。KMP算法是对朴素匹配算法的改进,提出了一个很抽象的概念:部分匹配值。这个概念的意思是:在一个串里面前缀和后缀的最长的子串的长度。所以要理解KMP还要明白前缀和后缀指的是什么。

    建议仔细阅读阮一峰的 博客,写得图文并茂通俗易懂,或者图灵社区的 文章。少啰嗦,先看东西:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define N 100
    
    void cal_next( char * str, int * next, int len )
    {
    	int i, j;
    
    	next[0] = 0;
    	for( i = 1; i < len; i++ )
    	{
    		j = next[ i - 1 ];
    		while( str[ j ] != str[ i ] &&  j > 0  )
    		{
    			j = j - 1;
    		}
    		if( str[ i ] == str[ j ] )
    		{
    			next[ i ] = j + 1;
    		}
    		else
    		{
    			next[ i ] = 0;
    		}
    	}
    }
    
    //返回值:模式字符串在源字符串第一次匹配的位置
    int KMP( char * str, int slen, char * ptr, int plen, int * next )
    {
    	int s_i = 0, p_i = 0;
    
    	while( s_i < slen && p_i < plen )
    	{
    		if( str[ s_i ] == ptr[ p_i ] )
    		{
    			s_i++;
    			p_i++;
    		}
    		else
    		{
    			if( p_i == 0 )
    			{
    				s_i++;
    			}
    			else
    			{
    				p_i = next[ p_i - 1 ];
    			}
    		}
    	}
    	return ( p_i == plen ) ? ( s_i - plen ) : -1;
    }
    
    int main()
    {
    	char str[ N ] = "ABCDAB ABCDABE ABCD";
    	char ptr[ N ] = "ABAABCABA";    //next: 0 0 1 1 2 0 1 2 3
    	//char ptr[N] = "ABCDAB";       //next: 0 0 0 0 1 2
    	//char ptr[N] = "AABCABCD";     //next: 0 1 0 0 1 0 0 0
    	int slen, plen;
    	int next[ N ];
    
    	slen = strlen( str );
    	plen = strlen( ptr );
    	cal_next( ptr, next, plen );
    	printf( "matched at: %d
    ", KMP( str, slen, ptr, plen, next ) );
    
    	return 0;
    }
    

    反思:
    由于朴素匹配算法在匹配失败的时候要从模式字符串的第一个字符重新开始,所以朴素匹配算法的时间复杂度是O(n*m)。而KMP有效的避免了重复搜索,所以时间复杂度是O(n+m)。

  • 相关阅读:
    Splunk 8.2.4破解每日500M限制
    wargame之Natas解题过程记录
    Linux提权方法小结
    Splunk安装
    从原理学习Java反序列化
    getshell之后
    VulnStack靶机练习
    eclipse 3.7安装扩展心得
    yarn 切换node版本
    Rreact如何调取后端接口发起PC端项目支付宝支付请求?
  • 原文地址:https://www.cnblogs.com/ingvar/p/5984725.html
Copyright © 2020-2023  润新知