字符串匹配kmp

算法原理:http://wiki.jikexueyuan.com/project/kmp-algorithm/define.html

#include<iostream>
#include<string>
#include<string.h>
using namespace std;

//给定两个字符串,判断其中一个是否包含另一个,如果包含则返回起始位置
//next[i]的含义是,i位之前的字符串拥有的最长前缀和最长后缀相同的长度。
//最长前缀:是说以第一个字符开始,但是不包含最后一个字符。

//KMP的原理在于,将暴力破解中重复的遍历用一个NEXT数组记录模式串前缀和后缀相同的方式记录下来
//匹配失败后可以从最长前缀跳到最长后缀,中间可跳是因为:
//如果存在其他相同的字符串,那么前缀和后缀相同的数目就会增大,这与得到的相同最长前缀和后缀相矛盾
//

int getIndexOf(string s, string m){ //传入两个字符串
	//s原字符串   m 匹配字符串

	//边界条件判断
	if (s.empty() == 1 || m.empty() == 1 || m.length() < 1 || s.length() < m.length()){
		return -1;
	}
	//字符串变为字符数组
	char ss[100];
	strncpy_s(ss, s.c_str(), s.length());

	////
	//for (int i = 0; i< s.length(); i++){
	//	std::cout << ss[i];
	//}
	//std::cout<< std::endl;
	////
	char ms[100];
	strncpy_s(ms, m.c_str(), m.length());
	//
	//for (int i = 0; i < m.length(); i++){
	//	std::cout << ms[i];
	//}
	//std::cout << std::endl;
	////
	int si = 0;
	int mi = 0;

	//计算next数组
	//最长相同前缀后缀长度值右移一位,然后初值赋为 - 1

	if (strlen(ms) == 0){
		return -1;
	}

	int next[10];
	next[0] = -1;
	next[1] = 0;
	int pos = 2; //从下标为2开始计算
	int cn = 0;  //最大值计数

	//在没有遍历完模式串的情况下
	while (pos < strlen(ms)){
		//比较两头的字符是否相同
		if (ms[pos - 1] == ms[cn]){
			next[pos++] = ++cn;
		} //不相同的话如果
		else if (cn > 0){ 
			cn = next[cn];
		}
		else{ //cn<=0  置为0
			next[pos++] = 0;
		}

	}
	//std::cout <<"strlen(ms) :" << strlen(ms)<<std::endl;

	////
	//for (int i = 0; i < strlen(ms); i++){
	//	cout << next[i];
	//}
	//std::cout << std::endl;

	////
    //	失配时,模式串向右移动的位数为,失配字符所在位置 - 失配字符对应的next 值
	while (si < strlen(ss) && mi < strlen(ms)){

		if (ss[si] == ms[mi]){ //原始数组中的两个串匹配,同时向右移动
			si++;
			mi++;
		} 
		else if (next[mi] == -1){ //原始串不匹配,且是模式串第一个元素
			si++;
		}
		else {  //模式串匹配了一部分之后,发现不匹配,向右移动原来的next个位数
			mi =next[mi];
		}
	}

	return mi == strlen(ms) ? si - mi : -1;     //串匹配结束不是因为匹配失败,那么返回匹配成功位置

}



int main(){
	string s = "abcabcacab";
	//    char ss[s.length()];
	//  std::cout<< s.length()<<std::endl;   5
	string match = "acab";
	//    strncpy(ss,s.c_str(),s.length());
	//    std::cout<<strlen(ss)<<std::endl;
	//    std::cout<<sizeof(ss)<<std::endl;
	
	std::cout <<"the result is: "<< getIndexOf(s, match) << std::endl;

	return 0;
}

猜你喜欢

转载自blog.csdn.net/liu_fei_er/article/details/80173117