zoukankan      html  css  js  c++  java
  • KMP字符串匹配算法

    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。

    KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。即确定下一次应该从那个位置重新开始匹配。

    char*obj = "cbcba";

    char*src = "sdcbcbcba";

    要在src中寻找obj,过程如下:

    从src第0位开始匹配,s匹配失败,移动1位,

    从d开始匹配,d匹配失败,移动1位,

    接着从src第2位c开始,匹配,继续b,匹配,继续c,匹配,继续b,匹配,继续c,不匹配,

    KMP算法关键点就在这里,要移动最大的距离,在这里是2位,即从src第二位移动到第四位,下次从第四位的c开始匹配。

    对于一个要查找的目标字符串,每次在哪一位匹配失败后要移动的最大距离可以提前算出来,存到一个数组里,匹配时直接查找就行。


    纯粹自己实现,代码有些丑陋,呵呵


    // KMP.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include<iostream>
    using namespace std;
    
    int*kk;
    int*kkk;
    
    int KMP(char*src, char*obj)
    {
    	int k1 = 0; 
    	int k2 = 0;
    	int len1 = strlen(src);
    	int len2 = strlen(obj);
    	while (k1 < len1)
    	{
    		if (src[k1] != obj[0])
    		{
    			++k1;
    			continue;
    		}
    		while (k2 < len2+1&&k1+k2 < len1+1)
    		{
    			if (k2 == len2)
    				return k1;
    			if (src[k1 + k2] == obj[k2])
    				++k2;
    			else 
    				if (kkk[k2] == 1)
    				{
    				k1 = k1 + kk[k2];
    				k2 = 0;
    				continue;
    				}
    				else
    					if (obj[k2 - kk[k2]] == src[k1 + k2])
    					{
    				k1 = k1 + kk[k2];
    				k2 = 0;
    				continue;
    					}
    					else
    					{
    						k1 = k1 + k2 + 1;
    						k2 = 0;
    						continue;
    					}
    
    		}
    	}
    
    	return -1;
    
    }
    
    
    int* shift(char*obj)
    {
    	int len = strlen(obj);
    	kk = new int[len];
    	kkk = new int[len];
    	for (int i = 0; i < len; i++)
    	{
    		kkk[i ]= 0; 
    	}
    	kk[0] = 1;
    	if (len > 1)
    	{
    		if (obj[0] == obj[1])
    		{
    			kk[1] = 2;
    			kkk[1] = 1;
    		}
    		else
    			kk[1] = 1;//条件是src与obj第1位匹配的字符等于obj第0个字符,否则kk[1]=2,这由匹配时的src决定
    	}
    	
    
    	int k = 2;
    	int n = 0;
    	int m = 1;
    	while (k < len)
    	{
    		bool flag = false;
    		bool flag1 = false;
    		while (m<k)
    		{
    			
    			if (obj[m] != obj[n])
    			{
    				++m;
    				continue;
    			}
    			while (obj[m] == obj[n])
    			{
    				flag1 = true;
    				if (m == k - 1)
    				{
    					flag = true;
    					break;
    				}
    				++m;
    				++n;
    			}
    			if (flag)
    				break;
    		}
    		if (!flag1)
    			if (obj[k] == obj[0])
    			{
    			kk[k] = k + 1;//此时直接后移,src无需判断
    			kkk[k] = 1;
    			n = 0;
    			m = 1;
    			++k;
    			continue;
    			}
    		if (obj[k] == obj[n + 1])
    		{
    			kk[k] = k + 1;//此时直接后移,src无需判断
    			kkk[k] = 1;
    			n = 0;
    			m = 1;
    			++k;
    			continue;
    		}
    		if (flag)
    			kk[k] = k - 1 - n;//此处假设src与obj第k位匹配的字符等于obj第n+1个字符,否则kk[k]=k+1,kmp匹配时需做判断
    		else
    			kk[k] = k;//此处假设src与obj第k位匹配的字符等于obj第0个字符,否则kk[k]=k+1,kmp匹配时需做判断
    		n = 0;
    		m = 1;
    		++k;
    
    	}
    
    	return kk;
    }
    
    
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	//char*obj = "cbcba";
    	//char*src = "sdcbcbcba";
    	//char*src = "abacaabacabacabaabb";
    	//char*obj = "abacab";
    	char*src = "BBC ABCDAB ABCDABCDABDE";
    	char*obj = "ABCDABD";
    	int len = strlen(obj);
    	shift(obj);
    	for (int i = 0; i < len; i++)
    		cout << kk[i] << endl;
    	cout << endl;
    	for (int i = 0; i < len; i++)
    		cout << kkk[i] << endl;
    	cout << KMP(src, obj) << endl;
    	system("pause");
    	return 0;
    }
    



    版权声明:

  • 相关阅读:
    div 背景透明,字体不透明
    弹性盒子(1)
    小练习(4)
    小练习(3)
    图标文字上拉效果
    小练习(2)
    小练习
    css的使用(1)
    复合的使用
    表单元素的使用 form input
  • 原文地址:https://www.cnblogs.com/walccott/p/4956909.html
Copyright © 2011-2022 走看看