KMP算法(《算法导论》)

来源:互联网 发布:java中long转int 编辑:程序博客网 时间:2024/05/17 08:58

#include 
<iostream>
#include 
<string>
#include 
<assert.h>
using std::string;
using std::cout;
using std::endl;
class KMP
{
 
public:
    KMP(
char* source, char*Pattern):source(source),Pattern(Pattern){V = NULL;}
    KMP(
const KMP& rh)
    
{
        assert(
&rh != this);
        source  
=  rh.source;
        Pattern 
= rh.Pattern;
        V 
= rh.V;
    }

    KMP
& operator=(KMP& rh)
    
{  
        assert(
&rh != this);
        source  
=  rh.source;
        Pattern 
= rh.Pattern;
        V 
= rh.V;
        
return rh;
    }

    
int* Compute_Prefix_Function(char* Pattern)
    
{
      
int m = strlen(Pattern);
      V 
= new int[m];
      memset(V, 
0, m * sizeof(int));
      V[
0= 0;
      
int k =0 ;
      
for(int q = 2; q < m; q++)
      
{   
        
while((k > 0&& (Pattern[k+1!= Pattern[q]))
            k 
= V[k];
        
if(V[k] == Pattern[q-1])
            k 
= k + 1;
        V[q
-1= k;
      }

      
return V;
    }

   
void    KMP_Matcher()
    
{
      
int n = strlen(source);
      
int m = strlen(Pattern);
      
int* V = Compute_Prefix_Function(Pattern);
      
int q = 0;
      
for(int i = 1; i <=n; i++)
       
{
         
while(q > 0 && Pattern[q] != source[i-1])
            q 
= V[q-1];
          
if(Pattern[q] == source[i-1])
            q 
= q + 1;
          
if(q == m)
          
{
           cout
<<" Pattern occurs with shift  " <<i-m<<endl;
           q 
= V[q-1];
           }

        }

        
    }

~KMP(){ delete []V; }
 
private:
    
char* source;
    
char* Pattern;
    
int* V;
}
;


int main(int argc, char* argv[])
{   
    
char m[] = "l111111112klajia211bcabd112";
    
char n[] = "112";
    KMP par(m, n);
    KMP pa 
= par;
    pa.KMP_Matcher();
    
return 0;
}

// KMP.cpp : Defines the entry point for the console application.
//
//《算法导论》569页。模式匹配在于计算前缀与后缀的匹配,只有这样,才能把
//前缀移位到当初匹配的后缀。因为是在前缀和后缀匹配的情况下。
#include "stdafx.h"
#include 
<iostream>
#include 
<string>
using std::string;
using std::cout;
using std::endl;

int* Compute_Prefix_Function(char* P)
{
    
int m = strlen(P);//计算模式的长度
    int *= new int[m];//申请空间
    memset(V, 0, m*sizeof(int));//初始化为0
    V[0= 0;
    
int k =0 ;
    
for(int q = 2; q < m; q++)
    
{   //V[k]实际上是指第k个字符的最长前缀和后缀相等.《算法导论》(图32—10 |图32-11)有详细说明.
        while((k > 0&& (P[k+1!= P[q]))//当第k+1个字符和第q个字符不相等,本质就是V[k+1]不存在前缀和后缀相等
            k = V[k];//循环搜索所有的V[k]值,直到找到一个P[k+1] ==P[q]的值为止。还存在k=0和p[0] ==p[q-1]的情况
        if(V[k] == P[q-1])
            k 
= k + 1;
        V[q
-1= k;
    }

    
return V;
}

void KMP_Matcher(char* T, char* P)
{
    
int n = strlen(T);
    
int m = strlen(P);
    
int* V = Compute_Prefix_Function(P);
    
int q = 0;
    
for(int i = 1; i <=n; i++)
    
{
        
while(q > 0 && P[q] != T[i-1])
            q 
= V[q-1];
        
if(P[q] == T[i-1])
            q 
= q + 1;
        
if(q == m)
        
{
        
          cout
<<" Pattern occurs with shift  " <<i-m<<endl;
          q 
= V[q-1];
        }

        
    }

    
   delete []V;
}



int main(int argc, char* argv[])
{   
    
char m[] = "l111111112klajia211bcabd112";
    
char n[] = "112";
    KMP_Matcher(m, n);
    
return 0;
}

 
原创粉丝点击