KMP串匹配算法

KMP和普通的比较在于,不是一个字符一个字符的比较,因为那样很浪费时间,而是在事先对我要比对的子串进行一次reckonValue,即计算每个字符在这个字符串中的value值,在和主串进行比较,当遇到不同的字符时候,根据value值重新定位下一个要比较的字符,避免从来再比较而造成的时间浪费!

下面是笔者这几天抽空写出的c语言描述算法,经过测试,给大家学习参考交流一下!

 

[c-sharp]  view plain copy
  1. /********************************************************************** 
  2. 头文件------head file 
  3. **********************************************************************/  
  4. #include <stdio.h>  
  5. #include <stdlib.h>  
  6. #include <string.h>  
  7. /********************************************************************** 
  8. 宏定义------macro definition 
  9. **********************************************************************/  
  10. #define EQ( a, b)   a == b  && (a & b)  //判断是否相等的宏定义  
  11. #define debug       1                   //调试用的裁剪宏定义  
  12.   
  13. /************************************************************************* 
  14. 结构体的定义-----------struct definition 
  15. *************************************************************************/  
  16. typedef struct   
  17. {  
  18.     char data;  
  19.     int value;  
  20. }Value;  
  21.   
  22. /************************************************************************* 
  23. 函数名称:__reckonValue 
  24. 函数表述: 为内部函数,用于KMP匹配算法时,计算value的值 
  25. 输入值:  string *child 
  26. 返回值:  计算成功返回计算后的结果,否则返回NULL 
  27. *************************************************************************/  
  28. Value * __reckonValue(char *child)  
  29. {  
  30.     int i,j;                        //计算value的两个变量  
  31.     int length;                     //存入长度  
  32.     Value *datavalue;  
  33.   
  34.     length  =   strlen(child);  
  35.   
  36.     datavalue = (Value *)malloc(sizeof(Value)*length);  
  37.     if(datavalue == NULL)  
  38.     {  
  39.         puts("为KMP算法计算value开辟空间失败");  
  40.         return NULL;  
  41.     }  
  42.   
  43.     for(i = 0; i < length; i++)  
  44.     {  
  45.         datavalue[i].data = child[i];   //将值传入到数组中  
  46.     }  
  47.   
  48.     datavalue[0].value = 0;         //初始化第一个字符为0  
  49.     i = 1;                          //i指向第二个字符  
  50.   
  51.     while(i <= length)  
  52.     {  
  53.         j = i - 1;  
  54.   
  55.         while(datavalue[i].data != datavalue[j].data    //停止的条件为扫描  
  56.               && j > 0)                                  //到第0个数据了或者遇到相等的数据  
  57.         {  
  58.             j --;  
  59.         }  
  60.   
  61.         datavalue[i].value = datavalue[j].value + 1;    //加1,得到value  
  62.         i ++;                                           //计算后一个  
  63.     }  
  64.  
  65. #if debug == 1  
  66.     for(i = 0;i < length;i ++)  
  67.     {  
  68.         printf("%c  ",datavalue[i].data);  
  69.     }  
  70.     puts("");  
  71.     for(i = 0;i < length;i ++)  
  72.     {  
  73.         printf("%d  ",datavalue[i].value);  
  74.     }  
  75.     puts("");  
  76. #endif  
  77.   
  78.     return datavalue;  
  79. }  
  80.   
  81. /************************************************************************* 
  82. 函数名称:matchString 
  83. 函数表述: KMP串匹配算法的主要函数 
  84. 输入值:  string *main,string *child 
  85. 返回值:  匹配成功返回子串在主串中的起始位置,否则返回-1 
  86. *************************************************************************/  
  87. int matchString(char *main,char *child)  
  88. {  
  89.     Value *childvalue;                      //接收value 值  
  90.     int mainlength,childlength;  
  91.     int i,j;  
  92.   
  93.     mainlength  =   strlen(main);  
  94.     childlength =   strlen(child);  
  95.   
  96.     if(main == NULL                         //判断主串与子串是不是合法的  
  97.      ||child == NULL)  
  98.     {  
  99.         puts("字符串不合法");  
  100.         return -1;  
  101.     }  
  102.     else if(mainlength < childlength)        //判断主串与子串在长度上是否合法  
  103.     {  
  104.         puts("子串长度大于主串长度");  
  105.         return -1;  
  106.     }  
  107.   
  108.     childvalue = __reckonValue(child);      //调用内部函数,计算value的值  
  109.       
  110.     i = 0;  
  111.     j = 0;  
  112.     while(i <= mainlength && j <= childlength)  
  113.     {  
  114.         for(;EQ(main[i],child[j]);i++,j++); //进行比对  
  115.   
  116.         if(j == childlength )  
  117.         {  
  118.             return i - childlength ;    //此时表示是子串返回初始位置  
  119.         }  
  120.         i ++;                               //若不成功则继续运行算法  
  121.         j = childvalue[j].value;            //重新定位j,为次元素的跨度  
  122.     }  
  123.   
  124.     return -1;  
  125. }  
  126.   
  127. int main()  
  128. {  
  129.     char child[]        =   "abcacabc";  
  130.     char main[]         =   "ababcabcacabc";  
  131.   
  132.     printf("%d/n",matchString(main,child));  
  133.     return 0;  
  134. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值