您的位置:首页 > 其它

字符串匹配:暴力,KMP,horsepool实现(1)

2017-10-24 17:41 267 查看
字符串匹配:暴力,KMP,horsepool实现(1)

#include
/*结尾字符*/
#define NVL '*'
/*字符串匹配算法
*tips:都是用最坏情况,描述时间渐进复杂度
*/
/*暴力搜索 O(n) = O(n^2)*/
int BF(char* W,char* T){
int i,j;

for(i=0,j=0;W[i]!=NVL;){
if(T[j]==NVL) return i-j;
if(T[j] == W[i]){j++;i++;}
else if(j==0){ i++;}
else{j=0;}
}
return -1;
}

/*KMP算法
*在模式串T[0],T[1]...T
中可能存在T[0]...T[k-1] == T[j-k+1]...T[j] k个首尾相同的子串。
*则当模式串T[j+1]与待匹配字串W[i+1]不匹配时,存在T[0]...T[k-1]==T[j-k+1]...T[j]==W[i-k+1]...W[i]的关系
*则可以直接拿T[(k-1)+1]与W[i+1]相比,而不是拿T[0]与W[i+1]相比

*设计:
*假设与T[]同长数组NEXT[]指示满足上述关系的下标 k-1。
*	1.W长度>=2.
*	2.NEXT[0]=-1 指示向右挪一位
*

*	3.NEXT[i]=NEXT[i-1] + W[NEXT[i-1]+1]==W[i]?1:0;
*
*/

void GetNext(char* W,int *next){
int i,j;
for(i=0;W[i]!=NVL;i++){
if(i==0) {*(next) = -1;}
else if(i==1) {*(next+1) = W[0]==W[1]?0:-1;}
else {
j = next[i-1];
if(W[j+1]==W[i]){
next[i]=j+1;
}
else{
next[i]=-1;
}
}
}
}
/*KMP的算法好坏取决于,模式串中Next[]数组指向最大的重复字符串
*关键在于:Next[]如何指向最大的下标?
*O(n) = O(MN)
*/
int KMP(char* W,char*T){
int next[255]={0};
int i,j;
GetNext(T,next);
for(i=0,j=0;W[i]!=NVL;){
if(T[j]==NVL) return i-j;
if(W[i]==T[j]){i++;j++;}
else{
if(j==0){ i++;j=0;}
else j=next[j-1]+1;
}
}
return -1;
}
/*Horsepool创新从右向左比较,尽可能的使模式字符串向后跑 比KMP要好理解 且节省空间*/
int Horsepool(char* W,char* T){
int i,j,k1,k2;
for(i=0;T[i]!=NVL;i++);
i=j=i-1; //第一次ij的比较位置,默认T长度是小于等于W的长度
for(;W[i]!=NVL;){
k1=k2=0;
while(k2<=j&&k1<=i&&W[i-k1]==T[j-k2]){ k1++;k2++;} //找到不匹配位置 A
if(k1>j) return i-k1+1;//找到
while(k2<=j&&W[i-k1]!=T[j-k2]) k2++;//找到与A位置匹配的左边字符的位置B
i+=k2-k1; //A B对其,进行下一次匹配
}
return -1;
}

int main(void) {
// your code goes here
char W[100]={'\0'},T[100]={'\0'};
int next[255]={};
int i;

scanf("%s %s",W,T);
// 	 printf("%d\n",BF(W,T));
// 	 printf("%d\n",KMP(W,T));
printf("%d\n",Horsepool(W,T));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: