模式匹配--KMP算法

问题:输入一个字符串,然后输入该字符串的子串或者任意长度的字符串,将第一次出现的该字符串的子串删除,输出新的字符串,具体见示例输入输出.

sample1 input
ABCDEFG 
CDE
sample1 output
ABCDEFG-CDE=ABFG

sample2 input
123456723
672
sample2 output
123456723-672=123453
  • 思路一:穷举搜索,直接从第一个主串元素开始匹配,朴素版本的kmp算法,时间复杂度O(lstr*lstrsub);
  • 其中lstr表示主串的长度,lstrsub子串的长度,时间效率低.
#include<stdio.h>
#include<string.h>
const int maxa=10000;
char s[maxa],sub[maxa];
void delsubstr(char *s,char *sub){
	int ls=strlen(s),lsub=strlen(sub);
	int cnt=0,addr=-1;
	int i,j;
	printf("%s-%s=",s,sub);
	for(i=0;i<ls;i++){
		for(j=0;j<lsub;j++){
			if(sub[j]==s[i+j])
				cnt++;
		}
		if(cnt==lsub){
			addr=i;
			break;
		}
		cnt=0;
	}
	if(addr==-1){
		printf("不存在\n");
	}else{
		for(i=0;i<addr;i++)
			printf("%c",s[i]);
		for(i=addr+lsub;i<ls;i++)
			printf("%c",s[i]);
		printf("\n");
	}

}
int main(){
	printf("输入0 0结束程序: \n");
	while(1){
		scanf("%s %s",s,sub);
		if(!strcmp(s,"0")&&!strcmp(sub,"0"))	break;
		delsubstr(s,sub);
	}
	return 0;
}
  • 思路二:kmp算法模板求解,时间复杂度O(lstr);参考《数据结构与算法》
  • 其中lstr表示主串的长度,此处时间复杂度为主串的长度,时间效率是思路一的lstrsub倍;
  • 当lstrsub长度超过1e5,算法性能就有很好的体现.
    #include<stdio.h>
    #include<string.h>
    const int maxa=10000;
    int next[maxa];
    int ls,lsub;
    char s[maxa],sub[maxa];
    void getnext(int m){
    	int i=0,j=-1;
    	next[i]=-1;
    	while(i<m){
    		if(j==-1||sub[i]==sub[j]){
    			next[++i]=++j;
    		}
    		else j=next[j];
    	}
    } 
    int kmp(int pos,int lsub,int ls){
    	int i=pos,j=0,ans,flag=0;
    	while(i<ls){
    		if(sub[j]==s[i]||j==-1){
    			++i;
    			++j;
    		}
    		else j=next[j];
    		if(j==lsub){
    			ans=i;
    			flag=1;
    			break;
    		}
    	}
    	if(flag)	return ans-lsub+1;
    	else return -1;
    }
    void delsubstr(char *s,char *sub){
    	int addr=kmp(0,lsub,ls);
    	int i,j;
    	printf("%s-%s=",s,sub);
    	if(addr==-1)	printf("不存在\n");
    	else{
    		for(i=0;i<addr-1;i++)
    			printf("%c",s[i]);
    		for(i=addr+lsub-1;i<ls;i++)
    			printf("%c",s[i]);
    		printf("\n");
    	}
    	return;
    }
    int main(){
    	printf("输入0 0结束程序: \n");
    	while(1){
    		scanf("%s %s",s,sub);
    		ls=strlen(s),lsub=strlen(sub);
    		if(!strcmp(s,"0")&&!strcmp(sub,"0"))	break;
    		getnext(lsub);
    		delsubstr(s,sub);
    	}
    	return 0;
    }

     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值