加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

字符串匹配算法(C语言)

(2011-06-16 16:21:45)
标签:

杂谈

分类: 课程记录

串的模式匹配算法

计算机上的非数值处理的对象基本上是字符串数据,在信息检索系统中,也是以字符串作为处理对象的。其中字符串的匹配操作广泛应用于建立词汇索引表等操作中,可见字符串的匹配操作在信息检索系统中是相当重要的。

子串的定位操作通常叫做串的模式匹配(其中T称为模式串),是各种串处理系统中的重要操作之一。严蔚敏版的《数据结构》教材上介绍了3种方式用于实现串的模式匹配(详细描述见课本P72P79-P84),现简单介绍如下:

1.利用判等、求串长和求子串等操作来实现

基本思想:在主S中取从第ii的初值为pos)个字符起、长度和串T相等的子串和串T比较,若相等,则求得函数值为i,否则i值增1直至串S中不存在和串T相等的子集为止。

int Index (String S, String T, int pos) {

 // T为非空串。若主串S中第pos个字符之后存在与 T相等的子串,

 //则返回第一个这样的子串在S中的位置,否则返回0

  if (pos 0) {

    StrLength(S);  StrLength(T);  pos;

    while <= n-m+1) {

        SubString (sub, S, i, m);

        if (StrCompare(sub,T) != 0)   ++i ;

        else return ;

    // while

  // if

  return 0;          // S中不存在与T相等的子串

// Index

 

2.简单的匹配算法

int Index(SString S, SString T, int pos) {

       // 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0

      // 其中,T非空,1posStrLength(S)

    pos;   1;

    while (i <= S[0] && <= T[0]) {

      if (S[i] == T[j]) ++i;  ++j; }// 继续比较后继字符

      else i-j+2;   1;   // 指针后退重新开始匹配

    }

   if (j T[0])  return  i-T[0];

   else return 0;

 // Index

 

3.KMP匹配算法

 int Index_KMP(SString S, SString T, int pos) {

     // 利用模式串Tnext函数求T在主串S中第pos个字符之后的位置的

     //KMP算法。其中,T非空,1posStrLength(S)

     pos;   1;

     while (i <= S[0] && <= T[0]) {

         if (j || S[i] == T[j]) ++i;  ++j; }

                                               // 继续比较后继字符

         else  next[j];                       // 模式串向右移动

     }//while

    if (j T[0])  return  i-T[0];                 // 匹配成功

    else return 0;

// Index_KMP

********************************************************

void get_next(SString &T, int &next[] {

   // 求模式串Tnext函数值并存入数组next

   1;   next[1] 0;   0;

    while (i T[0]) {

        if (j == || T[i] == T[j])

             {++i;  ++j; next[i] j; }

        else  next[j];

    }

// get_next

*********************************************************

   void get_nextval(SString &T, int &nextval[]) {

       //求模式串Tnext函数修正值并存入数组nextval

      1;   nextval[1] 0;   0;

      while (i T[0]) {

          if (j == || T[i] == T[j]) {

              ++i;  ++j;

              if (T[i] != T[j])  nextval[i] j;

              else  nextval[i] nextval[j];

         }

        else  nextval[j];

     }

  // get_nextval

 

 

 

 

 

 

 

 

 

 

 

 

 

程序清单

1.简单匹配程序 SimpleMatch.c

#include <stdio.h>

#include <string.h> 

int index(char *s,char *t,int pos); 

int pos=0; 

 

void main() 

char s[80];  char t[20];   int n

  printf("please input the string of S:\n");

  gets(s);

  printf("please input the string of t:\n");

  gets(t);

 

  n=index(s,t,pos); 

  if(n!=0)

    printf("\n模式串 在主串 中第 %d 个位置之后。\n\n",n); 

  else

    printf("\n主串中不存在与模式串相匹配的子串!\n\n");

 

int index(char *s,char *t,int pos){

 // 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0

 // 其中,T非空,1≤pos≤StrLen(S)

 int i=pos,j=1; 

 

 while (i<=(int)strlen(s)&&j<=(int)strlen(t)) 

  if (s[i]==t[j-1]) ++ i++ j;}    //继续进行后续字符串的比较

  else {i=i-j+2;j=1;            //指针后退重新开始匹配

 

 if (j>(int)strlen(t))  return i-strlen(t)+1; //匹配成功

 else //匹配不成功

 return 0; 

//index

 

 

2.未修正next函数值的KMP匹配程序 KMP1.c

#include <stdio.h>

#include <string.h> 

int index_KMP(char *s,char *t,int pos); 

void get_next(char t,int next); 

 

int next[20]; 

int pos=0; 

 

void main() 

char s[80];  char t[20];   int n

  printf("please input the string of S:\n");

  gets(s);

  printf("please input the string of t:\n");

  gets(t);

 

  get_next(t,next); 

  n=index_KMP(s,t,pos); 

  if(n!=0)

   printf("\n模式串 在主串 中第 %d 个位置之后。\n\n",n); 

  else

   printf("\n主串中不存在与模式串相匹配的子串!\n\n");

 

int index_KMP(char *s,char *t,int pos

//利用模式串的TNEXT函数求t在主串s中的第pos个位置之后的位置的KMP算法。

//其中,t非空,1<=pos<=Strlength(s)

 int i=pos,j=1; 

 while (i<=(int)strlen(s)&&j<=(int)strlen(t)) 

  if (j==0||s[i]==t[j-1]) //继续进行后续字符串的比较

  

   i++; 

   j++; 

  

  else j=next[j];      //模式串向右移动

 

 if (j>(int)strlen(t)) //匹配成功

 return i-strlen(t)+1; 

 else                  //匹配不成功

 return 0; 

 

void get_next(char *t,int *next

//求模式串tnext函数的并存入数组next[]中。

 int i=1,j=0; 

 next[0]=next[1]=0; 

 while (i<(int)strlen(t)) 

 

  if (j==0||t[i]==t[j]) 

   

    i++; 

    j++; 

    next[i]=j

   

  else j=next[j]; 

 

}//get_next

 

 

3.修正next函数值后的KMP匹配程序 KMP2.c

#include <stdio.h>

#include <string.h> 

int index_KMP(char *s,char *t,int pos); 

void get_nextval(char t,int nextval); 

 

int nextval[20]; 

int pos=0; 

 

void main() 

char s[80];  char t[20];   int n

  printf("please input the string of S:\n");

  gets(s);

  printf("please input the string of t:\n");

  gets(t);

 

  get_nextval(t,nextval); 

  n=index_KMP(s,t,pos); 

  if(n!=0)

   printf("\n模式串 在主串 中第 %d 个位置之后。\n\n",n); 

  else

   printf("\n主串中不存在与模式串相匹配的子串!\n\n");

 

int index_KMP(char *s,char *t,int pos

//利用模式串的TNEXTVAl函数求t在主串s中的第pos个位置之后的位置的KMP算法。

//其中,t非空,1<=pos<=Strlength(s)

 int i=pos,j=1; 

 while (i<=(int)strlen(s)&&j<=(int)strlen(t)) 

  if (j==0||s[i]==t[j-1]) //继续进行后续字符串的比较

  

   i++; 

   j++; 

  

  else j=nextval[j];      //模式串向右移动

 

 if (j>(int)strlen(t)) //匹配成功

 return i-strlen(t)+1; 

 else                  //匹配不成功

 return 0; 

 

void get_nextval(char *t,int *nextval

//求模式串tnext函数修正值并存入数组nextval[]中。

 int i=1,j=0; 

 nextval[0]=nextval[1]=0; 

 while (i<(int)strlen(t)) 

 

  if (j==0||t[i]==t[j]) 

   

    ++i

    ++j

 

if(t[i]!=t[j])  nextval[i]=j;

else  nextval[i]=nextval[j];

   

  else j=nextval[j]; 

 

}//get_nextval

 

 

4.文件中字符匹配程序FileKMP.c

采用未修正next函数值的KMP算法

#include <stdio.h>

#include <string.h> 

int index_KMP(char *s,char *t,int pos); 

void get_next(char t,int next); 

int exit();

int next[5]; 

int pos=0; 

 

void main() 

char s[1000];  char t[20];   int n

  FILE *fp

  if((fp=fopen("d:wenjian.txt","rt"))==NULL)

  printf("\nCannot open file strike any key exit!\n"); 

    exit(0); 

  }

  printf("The string in the file is:\n");

  fputs(fgets(s,1000,fp),stdout);

  printf("\nPlease input the string of t:\n");

  gets(t);

 

  get_next(t,next); 

  n=index_KMP(s,t,pos); 

  if(n!=0)

  printf("\n模式串 在主串 中第 %d 个位置之后。\n\n",n); 

  else

  printf("\n主串中不存在与模式串相匹配的子串!\n\n");

 

int index_KMP(char *s,char *t,int pos

//利用模式串的TNEXT函数求t在主串s中的第pos个位置之后的位置的KMP算法。

//其中,t非空,1<=pos<=Strlength(s)

 int i=pos,j=1; 

 while (i<=(int)strlen(s)&&j<=(int)strlen(t)) 

  if (j==0||s[i]==t[j-1]) //继续进行后续字符串的比较

  

   i++; 

   j++; 

  

  else j=next[j]; //模式串向右移动

 

 if (j>(int)strlen(t)) //匹配成功

 return i-strlen(t)+1; 

 else //匹配不成功

 return 0; 

 

void get_next(char *t,int *next

//求模式串tnext函数的并存入数组next[]中。

 int i=1,j=0; 

 next[0]=next[1]=0; 

 while (i<(int)strlen(t)) 

 

  if (j==0||t[i]==t[j]) 

   

    i++; 

    j++; 

    next[i]=j

   

  else j=next[j]; 

}//get_next

 

实验结果

1.程序123的结果均如下:

http://s15/bmiddle/7155aa134a5d011be390e&690

2.程序4的结果如下:

http://s11/bmiddle/7155aa134a5d01648b9da&690

 

 

http://s5/bmiddle/7155aa134a5d01b084084&690

 

 

http://s13/bmiddle/7155aa134a5d01a41dfcc&690

 

结果分析

    实验结果与在Word中进行字符统计的结果实质上是一致的。每个英文字母、英文标点或空格为1字符长度每个汉字和中文标点均占用2个字符长度,在汉语文档中,每个空格(即敲一次空格键)占有1个字符长度。如在“千古”之前有14个汉字,4个中文标点,1个空格,在“千古”之前有37个字符,故模式串在主串的第38个位置之后。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有