KMP string pattern matching (25 points) (3 methods)

Given two strings String and Pattern composed of English letters, it is required to find the position of the first occurrence of Pattern in String, and output the substring of String after this position. If not found, output "Not Found".

This question is designed to test the performance of various matching algorithms in various data situations. The characteristics of each group of test data are as follows:

Data 0: Small-scale string, the test is basically correct;
Data 1: Random data, String length is 10​5, Pattern length is 10;
Data 2: Random data, String length is 10​5, Pattern length is 102;
Data 3: Random data, String length is 10​5, Pattern length is 10​3;
Data 4: Random data, String length is 10​5, Pattern length is 10​4;
Data 5: String length is 10​6, Pattern The length is 105; the case where the end character does not match;
data 6: the length of String is 106 and the length of Pattern is 105; the case where the first character does not match is tested.
Input format:
Input the first line to give String, which is a string composed of English letters and no more than 10​6 in length. The second line gives a positive integer N (≤10), which is the number of pattern strings to be matched. In the following N lines, each line gives a Pattern, which is a string of English letters with a length not exceeding 10​5. Each string is non-empty and ends with a carriage return.

Output format:
For each Pattern, output the matching result according to the title.

Input sample:

abcabcabcabcacabxy
3
abcabcacab
cabcabcd
abcabcabcabcacabxyz

Sample output:

abcabcacabxy
Not Found
Not Found

Method 1: C++, mainly use string interception function, timeout, 21 points
#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;
} 

Insert picture description here

Method 2: I learned a new function, which is very easy to use and awesome! ! ! Attach a blog to explain, note that its parameter is a char array (according to the requirements of the title data, choose the size of the array to be opened), do not put the string inside! ! ! , And pay attention to its header file

strstr(str1,str2) function

#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;
}
Method 3: Follow the requirements of the topic obediently, use the KMP algorithm, don't use violent BF (big data will definitely time out)
#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;
} 

Guess you like

Origin blog.csdn.net/weixin_45845039/article/details/108905362