带*和?的KMP算法的两种实现方式

这两个都是我做助教的那个班的两个同学完成的,觉得她们做得不错,故贴出来共享。

第一个同学的实现:

#include<iostream.h>
#include<string.h>
#include<assert.h>
class String
{
private:
 char * str;
 int size;
public:
 String( char * s );
 ~String();
 
 
 int Strlen ( ) { return strlen( this -> str ) ; }                 //求长度
 char & operator [ ] ( int  i )  {  return  str [ i ] ; }             //重载下标运算符
};

String::String(char * s)
{
 size = strlen(s);
 str = new char[size + 1];
 assert(str != NULL);
 strcpy(str,s);
}
String::~String()
{
 delete str;
}
int * Nature(String & P)
{
 int len = P.Strlen() ;
 assert( len > 0 ) ;
 int * N = new int [ len ] ;
 assert( N != NULL ) ;
 if( P[0] == '*' )
  N[ 0 ] = -1 ;
 else
  N[ 0 ] = 0 ;
 int m = 0 ;
 int i = 1 ;
 while( m < len )
 {
  while( i < len && P[ i ] != '*')
  {
   int k = N[ i -1 ] ;
   if( P[ i ] == '?' || P[ k+m ] == '?')
    N[ i ] = k + 1 ;
   else
   {
    while( k > 0 && P[ i ] != P[ k+m ] && P[ k+m ] != '?')
     k = N[ k-1 ] ;
    if( P[ i ] == P[ k+m ] || P[ k+m ] == '?')
     N[ i ] = k + 1;
    else
     N[ i ] = 0;
   }
   i++;
  }
  while( P[ i ] == '*' )
  {
   N[ i ] = -1;
   i ++ ;
  }
  m =  i;
 }
 return N ;
}

int KMP( String & Target , String & Pat , int * N , int StartIndex )
{
 int i = 0 , count = 0 ;
 for( ; i < Pat.Strlen() ; i ++ )
  if( Pat[ i ] == '*' )
  count ++;
  int LastIndex = Target.Strlen() - Pat.Strlen() ;
 if( ( LastIndex - StartIndex ) + count < 0 )
  return ( -1 ) ;
 i = StartIndex ;
 int j = 0 ,m = 0 ;
 
 while( N[ j ] == -1 )
 {
  j ++;
  m ++;
 }
 int n ,k = 0;                   //n和k 用来记录开始匹配成功的位置
 while( i < Target.Strlen() )
 {
  while( Target[ i ] != Pat[ j ] && Pat[j ] != '?' && j > m )
   j = N[ j - 1 ] + m;
  if( Pat[j] == Target[i] || Pat[j ] == '?' )
  {  
   k++;
   if(k ==1 )
    n = i;

   j ++ ;
   m ++;
  }
   
  
  while( Pat[j] == '*')
  {
   j++;
   m++;
  }
  
  
  if( j == Pat.Strlen() )
  {
   cout<<"在位置 "<< n <<" 处匹配成功"<<endl;
      return n;
  } 
  i ++ ;
 }
 cout<<"匹配不成功"<<endl;
 return -1;
 
}
void main()
{
 String P( "*an*?g?" ) ;
 int *  N = Nature( P ) ;
 for( int i = 0 ; i < P.Strlen() ; i ++ )
  cout << N [ i ] << " ";
 cout << endl ;
 String T( "zhangg xiexzi afasdg");
 int a = KMP( T,P,Nature(P),0);
 
 
}


第二个同学的实现:

class string
{
public:
 string();
    string(char *s);
 ~string();
 char* replace(char A, char B);
 int*  Next( string P);
 int KMP_FindPat(string S,string P,int* N,int startindex);
 bool print();
protected:
 int   size;
 char* str;
};

#include<iostream.h>
#include<string.h>
//#include<stdlib.h>
#include"String.h"
#include<assert.h>

string::string()
{
 size=0;
 str=NULL;
}

string::string(char* s)
{
 assert(s!=NULL);
 str=new char[strlen(s)+1];
 assert(str);
 strcpy(str,s);
 size=strlen(str);

}
//析构函数destructor
string::~string()
{
  size=0;
}

char* string:: replace(char A,char B)
{
 for(int i=0;i<size;i++)
 {
  if(str[i]==A)
   str[i]=B;
 }
 return str;
}

bool string::print()
{
 for(int i=0;i<size;i++)
 {
  cout<<str[i];
 }
 cout<<endl;
 return true;
}

int*  string::Next( string P)
{
 int m =strlen(P.str);
 assert(m>0);
 int* N=new int [m];
 N[0]=0;
 assert(N!=0);
 for(int i=1;i<m;i++)
 {
  int k=N[i-1];
  while(P.str[i]!=P.str[k]!='?'!='*'&& k!=0  ) 
  {
   k=N[k-1];
  }
  if(P.str [i]==P.str [k]||P.str [k]=='?'||P.str [i]=='?'||P.str [k]=='*'||P.str [i]=='*')
  {
   N[i]=k+1;
  }
  else
  {
   N[i]=0;
  }
 }
 for(int j=0;j<m;j++)
 {
  cout<<N[j]<<" ";
 }
 cout<<endl;
 cout<<"The length of P :"<<strlen(P.str)<<endl;
 return N;
 
}

int string:: KMP_FindPat(string S,string P,int *N,int StartIndex)
{
 //int i;
 int m=0;
 int j=0;
 int LastIndex=strlen(S.str)-strlen(P.str);
 if(LastIndex<StartIndex)
 {
  return (-1);
 }
 for(int i=StartIndex;i<strlen(S.str);i++)
 {
  while(S.str[i]!=P.str[j] && j>0 && P.str[j]!='*'&& P.str[j]!='?')
  {
    j=N[j-1];
  }
    if(  P.str[j]=='*')
  {
   j=j+1;
   while (S.str[i+1]!=P.str[j] && i<strlen(S.str))
   {
    i++;
    m++;
   }
   if(i==strlen(S.str))
   {
    return -1;
   }
  }
  if(S.str[i]==P.str[j]||P.str[j]=='?')
  {
   j++;
  }
  
  if(j == strlen(P.str))
  {
   return (i-j+1-(m-1));
  }
 }
 return (-1);
}

#include"String.h"
#include<iostream.h>
#include<string.h>
void main()
{
 int *N;
 int n;
 //char* P="infinite";
 //char* S="infinishinfinfinite";
 string P("a*d*f");
    string S("sddddasdfhhhjf");
 P.print();
 S.print();
 N=P.Next(P);
    n=S.KMP_FindPat (S, P,N,0);
 cout<<n<<endl;
 
 /*for(int i=n;i<n+P.strlen();i++)
 {
  cout<<S.str[i];
 }*/
 cout<<endl;

}

 

posted on 2008-12-18 19:51  小橋流水  阅读(338)  评论(0编辑  收藏  举报

导航