/* *用KMP算法实现字符串匹配搜索方法 *该程序实现的功能是搜索本目录下的所有文件的内容是否与给定的 *字符串匹配,如果匹配,则输出文件名:包含该字符串的行 *待搜索的目标串搜索指针移动位数 = 已匹配的字符数 - 对应部分匹配值 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #define KEYWORD_MAX_LENGTH 100 //设定搜索串的最大长度 int kmp_table[KEYWORD_MAX_LENGTH]; //为搜索串建立kmp表 char prefix_stack[KEYWORD_MAX_LENGTH]; //前缀表达式栈 char suffix_stack[KEYWORD_MAX_LENGTH]; //后缀表达式栈 int keyword_length = 0; //搜索串的长度 int record_position[KEYWORD_MAX_LENGTH]; //记录与关键字串匹配源串中的位置 /* *GetMatchValue:获得字符串src的部分匹配值 "部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ABCDABD"为例, - "A"的前缀和后缀都为空集,共有元素的长度为0; - "AB"的前缀为[A],后缀为[B],共有元素的长度为0; - "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0; - "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0; - "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1; - "ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2; - "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0 */ int GetMatchValue(char *src) { int value = 0; int src_len = strlen(src); char *begin = src; //初始化指向字符串第一个字符 char *end = src + (src_len - 1); //初始化指向字符串最后一个字符 int i = 0; for(i=0;i<(src_len-1);i++) { prefix_stack[i] = *begin; suffix_stack[i] = *end; //待会prefix开头和suffix的结尾开始对比 begin++; end--; } char *p = prefix_stack; char *q = suffix_stack + (src_len - 2); //指向栈中最后一个元素 int flag = 0; //用一个标志位来确定后缀栈中到最后一个元素都与前缀栈中的符号匹配 while(q >= suffix_stack) { if(*p == *q) { value++; p++; flag=1; } else { flag = 0; } q--; } if(flag == 0) value = 0; return value; } /* *创建搜索字符串的KMP表 */ int Create_KMP_Table(char *str,int *table) { int i; char *dst; keyword_length = strlen(str); for(i=0;i<keyword_length;i++) { if(i == 0) { table[i] = 0; //第一个字符无前缀和后缀,所以为0 } else { dst = (char*)malloc((i+2)); if(dst == NULL) { printf("malloc space error! "); return EXIT_FAILURE; } strncpy(dst,str,(i+1)); //匹配str的前(i+1)个字符 dst[i+1] = '