KMP 串的模式匹配 (25分)(3种方法)

给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出。如果找不到,则输出“Not Found”。

本题旨在测试各种不同的匹配算法在各种数据情况下的表现。各组测试数据特点如下:

数据0:小规模字符串,测试基本正确性;
数据1:随机数据,String 长度为 10​5,Pattern 长度为 10;
数据2:随机数据,String 长度为 10​5,Pattern 长度为 102;
数据3:随机数据,String 长度为 10​5,Pattern 长度为 10​3;
数据4:随机数据,String 长度为 10​5,Pattern 长度为 10​4;
数据5:String 长度为 10​6,Pattern 长度为 105;测试尾字符不匹配的情形;
数据6:String 长度为 106 ,Pattern 长度为 105 ;测试首字符不匹配的情形。
输入格式:
输入第一行给出 String,为由英文字母组成的、长度不超过 10​6 的字符串。第二行给出一个正整数 N(≤10),为待匹配的模式串的个数。随后 N 行,每行给出一个 Pattern,为由英文字母组成的、长度不超过 10​5的字符串。每个字符串都非空,以回车结束。

输出格式:
对每个 Pattern,按照题面要求输出匹配结果。

输入样例:

abcabcabcabcacabxy
3
abcabcacab
cabcabcd
abcabcabcabcacabxyz

输出样例:

abcabcacabxy
Not Found
Not Found

方法一:c++,主要使用字符串截取函数,超时,21分
#include <iostream>
#include <string>
using namespace std;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	string s,p;
	int n;
	cin >> s;
	cin >> n;
	for(int i = 0;i<n;i++){
		cin >> p;
		bool flag = false;
		if(p.length()>s.length())
			cout << "Not Found" << endl;
		else{
			for(int j = 0;j<=s.length()-p.length();j++){
				if(s[j]==p[0]){
					string ss = s.substr(j,p.length());
					if(ss==p){
						cout << s.substr(j) << endl;;
						flag = true;
						break;
					}
				}
			}
			if(!flag)
				cout << "Not Found" << endl;
		}
	}
	return 0;
} 

在这里插入图片描述

方法二:学到了一个新的函数,挺好用的,厉害啊!!!附上一篇讲解的博客,注意它的参数是char数组(根据题目数据的要求,选择数组需要开辟的大小),不要把string往里边放!!!,同时注意它的头文件

strstr(str1,str2) 函数

#include <iostream>
#include <cstring>
using namespace std;

int main(){
	char s[1000001],p[100001];
	int n;
	cin >> s;
	cin >> n;
	for(int i = 0;i<n;i++){
		cin >> p;
		if(strstr(s,p))
			cout << strstr(s,p) << endl;
		else
			cout << "Not Found" << endl;
	}
	return 0;
}
方法三:按照题目要求乖乖来,使用KMP算法,不要用暴力BF哦(数据大肯定会超时的)
#include <iostream>
#include <string>
#include <cstring>
using namespace std;

int xnext[100001];

void get_next(string s){
	int i,j;
	i = 0;//后缀
	j = -1;//前缀
	xnext[0] = -1;
	while(i<s.length()){
		if(j==-1||s[i]==s[j]){
			i++;
			j++;
			xnext[i] = j;
		}
		else
			j = xnext[j];
	} 
}

int get_index(string s1,string s2){
	int i = 0;
	int j = 0;
	get_next(s2);
	while(i<s1.length()){
		if(j==-1||s1[i]==s2[j]){
			i++;
			j++;
		}
		else
			j = xnext[j];
		if(j==s2.length())
			return i-s2.length();
	}
	return -1;
}

int main(){
	string s,p;
	int n;
	cin >> s;
	cin >> n;
	for(int i = 0;i<n;i++){
		cin >> p;
		int res = get_index(s,p);
		if(res==-1)
			cout << "Not Found" << endl;
		else
			cout << s.substr(res) << endl;
	}
	return 0;
} 
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值