KMP

KMP算法用于解决字符串匹配问题,它能够在O(n+m)的时间内完成文本串与模式串的匹配。C与C++中也有提供字符串匹配函数,比如C中的strstr(),C++中string类下的find()函数,但是对于大数据效果都没有KMP好。KMP算法主要是计算失配指针next[],然后顺着失配边走,直到可以匹配为止。

计算失配指针next[];

void GetNext(){
	int m = strlen(t);                 //字符串t为模式串
	int k = 0;
	next[0] = next[1] = 0;
	for (int i = 1; i<m; i++){
		k = next[i];
		while (k && t[i] != t[k]) k = next[k];
		if (t[i] == t[k]) next[i+1] = k + 1;
		else next[i+1] = 0;
	}
}

完成字符串匹配;

void KMP(){ 
	int n = strlen(s);              //字符串s为文本串
	int m = strlen(t);
	GetNext();
	int k = 0;
	for (int i=0; i<n; i++){
		while (k && s[i] != t[k]) k = next[k];
		if (s[i] == t[k]) k++;
		if (k == m){}          //找到了一个匹配
	}
}

KMP模板题 poj3461

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<stack>
#define ll long long
#define MAX 1000010
#define INF INT_MAX
#define eps 1e-8

using namespace std;

char s[MAX],t[MAX];

int next[MAX];

void GetNext(){
	int m = strlen(t);
	int k = 0;
	next[0] = next[1] = 0;
	for (int i = 1; i<m; i++){
		k = next[i];
		while (k && t[i] != t[k]) k = next[k];
		if (t[i] == t[k]) next[i+1] = k + 1;
		else next[i+1] = 0;
	}
}

int KMP(){
	int cnt = 0;
	int n = strlen(s);
	int m = strlen(t);
	GetNext();
	int k = 0;
	for (int i=0; i<n; i++){ 
		while (k && s[i] != t[k]) k = next[k];
		if (s[i] == t[k]) k++;
		if (k == m) cnt++;
	}
	return cnt;
}

int main(){
	int  T;
	scanf("%d",&T);
	while (T--){
		scanf("%s%s",t,s);
		printf("%d\n",KMP());
	}
	return 0;
}



KMP算法的应用—求前缀字符串的最短循环节,有的前缀可能没有循环节,当 next[i]  && i % (i-next[i]) == 0,最短循环节为i / (i-next[i]);


#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<climits>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#include<string>
#include<set>
#include<stack>
#define ll long long
#define MAX 1000010
#define INF INT_MAX
#define eps 1e-8

using namespace std;

int next[MAX];
char t[MAX];

void GetNext(){  
    int m = strlen(t);             
    int k = 0;  
    next[0] = next[1] = 0;  
    for (int i = 1; i<m; i++){  
        k = next[i];  
        while (k && t[i] != t[k]) k = next[k];  
        if (t[i] == t[k]) next[i+1] = k + 1;  
        else next[i+1] = 0;   
	}  
}

int main(){
	int n,cas = 0;
	while (scanf("%d",&n) && n > 0){
		cas++;
		scanf("%s",t);
		GetNext();
		printf("Test case #%d\n",cas); 
		for (int i=2; i<=n; i++){
			if (next[i] && i % (i-next[i]) == 0){
				printf("%d %d\n",i, i / (i - next[i]));
			}
		}
		printf("\n");
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值