KMP和普通的比较在于,不是一个字符一个字符的比较,因为那样很浪费时间,而是在事先对我要比对的子串进行一次reckonValue,即计算每个字符在这个字符串中的value值,在和主串进行比较,当遇到不同的字符时候,根据value值重新定位下一个要比较的字符,避免从来再比较而造成的时间浪费!
下面是笔者这几天抽空写出的c语言描述算法,经过测试,给大家学习参考交流一下!
- /**********************************************************************
- 头文件------head file
- **********************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- /**********************************************************************
- 宏定义------macro definition
- **********************************************************************/
- #define EQ( a, b) a == b && (a & b) //判断是否相等的宏定义
- #define debug 1 //调试用的裁剪宏定义
- /*************************************************************************
- 结构体的定义-----------struct definition
- *************************************************************************/
- typedef struct
- {
- char data;
- int value;
- }Value;
- /*************************************************************************
- 函数名称:__reckonValue
- 函数表述: 为内部函数,用于KMP匹配算法时,计算value的值
- 输入值: string *child
- 返回值: 计算成功返回计算后的结果,否则返回NULL
- *************************************************************************/
- Value * __reckonValue(char *child)
- {
- int i,j; //计算value的两个变量
- int length; //存入长度
- Value *datavalue;
- length = strlen(child);
- datavalue = (Value *)malloc(sizeof(Value)*length);
- if(datavalue == NULL)
- {
- puts("为KMP算法计算value开辟空间失败");
- return NULL;
- }
- for(i = 0; i < length; i++)
- {
- datavalue[i].data = child[i]; //将值传入到数组中
- }
- datavalue[0].value = 0; //初始化第一个字符为0
- i = 1; //i指向第二个字符
- while(i <= length)
- {
- j = i - 1;
- while(datavalue[i].data != datavalue[j].data //停止的条件为扫描
- && j > 0) //到第0个数据了或者遇到相等的数据
- {
- j --;
- }
- datavalue[i].value = datavalue[j].value + 1; //加1,得到value
- i ++; //计算后一个
- }
- #if debug == 1
- for(i = 0;i < length;i ++)
- {
- printf("%c ",datavalue[i].data);
- }
- puts("");
- for(i = 0;i < length;i ++)
- {
- printf("%d ",datavalue[i].value);
- }
- puts("");
- #endif
- return datavalue;
- }
- /*************************************************************************
- 函数名称:matchString
- 函数表述: KMP串匹配算法的主要函数
- 输入值: string *main,string *child
- 返回值: 匹配成功返回子串在主串中的起始位置,否则返回-1
- *************************************************************************/
- int matchString(char *main,char *child)
- {
- Value *childvalue; //接收value 值
- int mainlength,childlength;
- int i,j;
- mainlength = strlen(main);
- childlength = strlen(child);
- if(main == NULL //判断主串与子串是不是合法的
- ||child == NULL)
- {
- puts("字符串不合法");
- return -1;
- }
- else if(mainlength < childlength) //判断主串与子串在长度上是否合法
- {
- puts("子串长度大于主串长度");
- return -1;
- }
- childvalue = __reckonValue(child); //调用内部函数,计算value的值
- i = 0;
- j = 0;
- while(i <= mainlength && j <= childlength)
- {
- for(;EQ(main[i],child[j]);i++,j++); //进行比对
- if(j == childlength )
- {
- return i - childlength ; //此时表示是子串返回初始位置
- }
- i ++; //若不成功则继续运行算法
- j = childvalue[j].value; //重新定位j,为次元素的跨度
- }
- return -1;
- }
- int main()
- {
- char child[] = "abcacabc";
- char main[] = "ababcabcacabc";
- printf("%d/n",matchString(main,child));
- return 0;
- }