模式匹配应用

来源:互联网 发布:手机淘宝网2016 编辑:程序博客网 时间:2024/05/22 02:24
比较经典的Brute-Force算法与KMP算法的效率的优劣。
#include <stdio.h>  #include <stdlib.h>  #include <string.h>    #define MAXSIZE 60    typedef struct  {      char str[MAXSIZE];      int length;  }SeqString;      int B_FIndex(SeqString S,int pos,SeqString T,int *count);  int KMP_Index(SeqString S,int pos,SeqString T,int next[],int *count);  void GetNext(SeqString T,int next[]);  void GetNextVal(SeqString T,int nextval[]);  void PrintArray(SeqString T,int next[],int nextval[],int length);  void StrAssign(SeqString *S,char cstr[]);//串的赋值操作  int StrEmpty(SeqString S);//判断串是否为空  int StrLength(SeqString S);//求串的长度操作  void StrCopy(SeqString *T,SeqString S);//串的复制操作  int StrCompare(SeqString S,SeqString T);//串的比较操作  int StrInsert(SeqString *S,int pos,SeqString T);//串的插入操作  int StrDelete(SeqString *S,int pos,int len);//串的删除操作  int StrConcat(SeqString *T,SeqString S);//串的连接操作  int SubString(SeqString *Sub,SeqString S,int poos,int len);//截取子串操作  int StrReplace(SeqString *S,SeqString T,SeqString V);//串的替换操作  int StrIndex(SeqString S,int pos,SeqString T);//串的定位操作  void StrClear(SeqString *S);//清空串操作  void StrPrint(SeqString S);//串的输出声明  #include "string.h"  /*经典的模式匹配算法Brute-Force*/  /*假设串采用顺序存储方式存储,则Brute-Force匹配算法如下*/    int B_FIndex(SeqString S,int pos,SeqString T,int *count)  /*在主串S中的第pos个位置开始查找子串T,如果找到,返回子串在主串中的位置;否则返回-1*/  {      int i,j;      i = pos-1;      j = 0;      *count = 0;      while(i < S.length && j < T.length)      {          if(S.str[i] == T.str[j])              /*如果串S和串T中对应的位置的字符相等,则继续比较下一个字符*/          {              i++;              j++;          }          else              /*如果当前对应位置的字符不相等,则从串S的下一个字符开始,从T的第0个字符开始比较*/          {              i = i-j+1;              j = 0;          }          (*count)++;      }      if(j >= T.length)          /*如果在串S中找到串T,则返回子串T在主串S中的位置*/      {          return i-j+1;      }      else      {          return -1;      }  }    /*KMP算法*/  /*KMP算法思想*/  /*利用模式串T的next函数值求T在主串S中的第pos个字符之间的位置的KMP算法描述如下:*/    int KMP_Index(SeqString S,int pos,SeqString T,int next[],int *count)  {      int i,j;      i = pos-1;      j = 0;      *count = 0;      while(i < S.length && j < T.length)      {          if(-1 == j || S.str[i] == T.str[j])              /*如果j=-1或当前字符相等,则继续比较后面的字符*/          {              i++;              j++;          }          else/*如果当前字符不相等,则将模式串向右移动*/          {              j = next[j];/*数组next保存next函数值*/          }          (*count)++;      }      if(j >= T.length)/*匹配成功,则返回子串T在主串S中的位置,否则返回-1*/      {          return i-T.length+1;      }      else      {          return -1;      }  }    /*求next函数值*/  /*算法描述如下*/  void GetNext(SeqString T,int next[])  {      int j,k;      j = 0;      k = -1;      next[0] = -1;      while(j < T.length)      {          if(-1 == k || T.str[j] == T.str[k])          {              j++;              k++;              next[j] = k;          }          else          {              k = next[k];          }      }  }    /*改进算法如下*/  void GetNextVal(SeqString T,int nextval[])  {      int j,k;      j = 0;      k = -1;      nextval[0] = -1;      while(j < T.length)      {          if(-1 == k || T.str[j] == T.str[k])          {              j++;              k++;              if(T.str[j] != T.str[k])              {                  nextval[j] = k;              }              else              {                  nextval[j] = nextval[k];              }          }          else          {              k = nextval[k];          }      }  }    void PrintArray(SeqString T,int next[],int nextval[],int length)  {      int j;      printf("j:\t\t");      for(j = 0;j < length;j++)      {          printf("%3d",j);      }      printf("\n");      printf("模式串:\t");      for(j = 0;j < length;j++)      {          printf("%3c",T.str[j]);      }      printf("\n");      printf("next[j]:\t");      for(j = 0;j < length;j++)      {          printf("%3d",next[j]);      }      printf("\n");      printf("nextval[j]:\t");      for(j = 0;j < length;j++)      {          printf("%3d",nextval[j]);      }      printf("\n");  }  void StrAssign(SeqString *S,char cstr[])//串的赋值操作(将常量cstr中的字符赋值给串S)  {      int i = 0;      for(i = 0;cstr[i]!='\0';i++)      {          S->str[i] = cstr[i];      }      S->length = i;  }  int StrEmpty(SeqString S)//判断串是否为空  {      if(S.length == 0)      {          return 1;      }      else      {          return 0;      }  }  int StrLength(SeqString S)//求串的长度操作  {      return S.length ;  }  void StrCopy(SeqString *T,SeqString S)//串的复制操作(将串S中的每一个字符赋给T)  {      int i;      for(i = 0;i < S.length ;i++)      {          T->str[i] = S.str[i];      }      T->length = S.length ;  }  int StrCompare(SeqString S,SeqString T)//串的比较操作  {      int i;      for(i = 0;i < S.length&&i < T.length ;i++)//比较两个串中的字符      {          if(S.str[i] != T.str[i])//如果出现字符不同,则返回两个字符的差值          {              return (S.str[i]-T.str[i]);          }      }      return (S.length - T.length);//如果比较完毕,返回两个字符串的长度的差值  }  int StrInsert(SeqString *S,int pos,SeqString T)//串的插入操作(在串S的pos个位置插入串T)  {      int i;      if(pos < 0 || pos-1 > S->length)      {          printf("插入位置不正确\n");          return 0;      }      if(S->length + T.length <= MAXSIZE)//子串完整插入到串中      {          //在插入子串T前,将S中的pos后的字符向后移动len个位置          for(i = S->length+T.length-1;i >= pos+T.length-1;i--)          {              S->str[i] = S->str[i-T.length];          }          //将串插入到S中          for(i = 0;i < T.length ;i++)          {              S->str[pos+i-1] = T.str[i];          }          S->length = S->length +T.length ;          return 1;      }      else if(pos +T.length <= MAXSIZE)//子串完全插入S中,但是S中的字符会被截断      {          for(i = MAXSIZE-1;i > T.length +pos-1;i--)          {              S->str[i] = S->str[i-T.length];          }          for(i = 0;i < T.length ;i++)          {              S->str[i+pos-1] = T.str[i];          }          S->length = MAXSIZE;          return 0;      }      else//子串T不能完全插入到S中,T将会有字符被舍弃      {          for(i = 0;i < MAXSIZE-pos;i++)          {              S->str[i+pos-1] = T.str[i];          }          S->length = MAXSIZE;          return 0;      }  }  int StrDelete(SeqString *S,int pos,int len)//串的删除操作(在串S中删除pos开始的len个字符,然后将后面的字符向前移动)  {      int i,flag;      if(pos < 0 || len < 0 || pos+len-1 > S->length)      {          printf("删除位置不正确,参数len不合法\n");          flag = 0;      }      else      {          for(i = pos+len;i <= S->length-1;i++)          {              S->str[i-len] = S->str[i];          }          S->length = S->length -len;//修改串S的长度          flag = 1;      }      return flag;  }  int StrConcat(SeqString *T,SeqString S)//串的连接操作(将串S连接在串T的后面)  {      int i,flag;      if(T->length +S.length <= MAXSIZE)      {          for(i = T->length ;i < T->length +S.length ;i++)          {              T->str[i] = S.str[i-T->length];          }          T->length = T->length +S.length ;          flag = 1;      }      else if(T->length < MAXSIZE)      {          for(i = T->length ;i < MAXSIZE;i++)          {              T->str[i] = S.str[i-T->length];          }          T->length = MAXSIZE;          flag = 0;      }      return flag;  }  int SubString(SeqString *Sub,SeqString S,int pos,int len)//截取子串操作(截取串S中从第pos个字符开始,长度为len的连续字符,并赋值给Sub)  {      int i;      if(pos < 0 || len < 0 || pos+len-1 > S.length)      {          printf("参数pos和len不合法\n");          return 0;      }      else      {          for(i = 0;i < len;i++)          {              Sub->str[i] = S.str[i+pos-1];          }          Sub->length = len;          return 1;      }  }  int StrIndex(SeqString S,int pos,SeqString T)//串的定位操作(在主串S中的第pos个位置开始查找子串T,如果主串S中存在与串T值相等的子串,返回子串在主串第pos个字符后第一次出现的位置)  {      int i,j;      if(StrEmpty(T))      {          return 0;      }      i = pos;      j = 0;      while(i < S.length && j < T.length)      {          if(S.str[i] == T.str[j])          {              i++;              j++;          }          else//如果当前对应位置的字符不相等,则从串S的下一个字符开始,从T的第0个字符开始比较          {              i = i-j+1;              j = 0;          }      }      if(j >= T.length)//如果在串S中找到串T,则返回子串T在主串S中的位置      {          return i-j+1;      }      else      {          return -1;      }  }  int StrReplace(SeqString *S,SeqString T,SeqString V)//串的替换操作(如果串S中存在子串T,则用V替换串S中的所有子串T)  {      int flag;      int i = 0;      if(StrEmpty(T))      {          return 0;      }      while(i)      {          i = StrIndex(*S,i,T);//利用串的定位操作在串S中查找T的位置          if(i)          {              StrDelete(S,i,StrLength(T));//如果找到子串T,则将S中的串T删除              flag = StrInsert(S,i,V);//将V插入              if(!flag)              {                  return 0;              }              i += StrLength(V);          }      }      return 1;  }  void StrClear(SeqString *S)//清空串操作  {      S->length = 0;  }  void StrPrint(SeqString S)//串的输出声明  {      int i;      for(i = 0;i < S.length ;i++)      {          printf("%c",S.str[i]);      }      printf("\n");  }  #include "string.h"    int main(void)  {      SeqString S,T;      int count1 = 0;      int count2 = 0;      int count3 = 0;      int find;      int next[40];      int nextval[40];      StrAssign(&S,"abaababaddecab");      StrAssign(&T,"abad");      GetNext(T,next);      GetNextVal(T,nextval);      printf("模式串T的next和改进后的next的值:\n");      PrintArray(T,next,nextval,StrLength(T));      find = B_FIndex(S,1,T,&count1);      if(find > 0)      {          printf("Brute-Force算法的比较次数为:%2d\n",count1);      }      find = KMP_Index(S,1,T,next,&count2);      if(find > 0)      {          printf("利用next的KMP算法的比较次数为:%2d\n",count2);      }      find = KMP_Index(S,1,T,nextval,&count3);      if(find > 0)      {          printf("利用nextval的KMP算法的比较次数为:%2d\n",count3);      }      StrAssign(&S,"cbccccbcacbccbacbccbcbcbc");      StrAssign(&T,"cbccbcbc");      GetNext(T,next);      GetNextVal(T,nextval);      printf("模式串T的next和改进后的next的值:\n");      PrintArray(T,next,nextval,StrLength(T));      find = B_FIndex(S,1,T,&count1);      if(find > 0)      {          printf("Brute-Force算法的比较次数为:%2d\n",count1);      }      find = KMP_Index(S,1,T,next,&count2);      if(find > 0)      {          printf("利用next的KMP算法的比较次数为:%2d\n",count2);      }      find = KMP_Index(S,1,T,nextval,&count3);      if(find > 0)      {          printf("利用nextval的KMP算法的比较次数为:%2d\n",count3);      }      return 0;  }  

运行结果如下:


0 0
原创粉丝点击