一个小的算法题,题目如题。什么意思呢?
就是一个很长的模式串例如“432A5234B5664C3243454”,再给一个目标串“ABC”,只要模式串中某一个字符串同事包含目标串中的每一个元素即可!
要求很低!很明显的用暴力匹配很容易就做出来了,但是暴力匹配算法的时间复杂度很低,是乘方级的(O(n^m))!KMP算法很难处理这种模糊的匹配。
如何才能提高效率呢,利用hash表就很容易解决这个问题,而且是一个相当简单的哈希表,非常有利于新人理解hash表。
由于字符串最多只有255位,所以这个hash表就只有0~255这些元素,根据ASCII表的码值作为hash数组的下标,如果在目标串中存在,相应的位置元素为1,
其余的位置都是0。这样我们可以构建一个数组来统计目标串的字符是否出现在模式串中。
代码时间,首先制作一个hash表,由于在main函数中,我已经将hash表的每一个元素都初始化为0,这样只要将相应位置修改即可:
/* 功能:实现一个比较高级的字符匹配算法,即一串很长的字符,要求找到符合要求字符的字符串 姓名:*** 时间:0:10 2014/1/18 */ #include<stdio.h> #include<stdlib.h> #include<string.h> /*制作hash表并初始化*/ void mkHash(char T[],char hash[],int n) { if(!T) { exit(-1); } for (int i = 0 ; i< n ; i++) { hash[T[i]] = 1; /*根据ASCII表的码值作为hash数组的下标*/ } }
下面这个函数就是某个字符是否在hash中出现了
int isExit(char str,char hash[]) { if(!hash) { exit(-1); } if(hash[str] == 0) { return 0; } else { return 1; } }
void getPos(char S[] , int n , char hash[]) { if(!S && !hash) { exit(-1); } for (int i=0;i<n;i++) { if(hash[S[i]] == 1) { printf("%d ",i+1); hash[S[i]] = 0; } } }
再从main引导:
int main() { char S[255]; char T[255]; char hash[255] = {0}; gets(S); gets(T); int Slen = strlen(S); int Tlen = strlen(T); mkHash(T,hash,Tlen); getPos(S,Slen,hash); system("pause"); return 0; }
好,看看输出: