串的模式匹配
串的模式匹配
给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出。如果找不到,则输出“Not Found”。
本题旨在测试各种不同的匹配算法在各种数据情况下的表现。各组测试数据特点如下:
- 数据0:小规模字符串,测试基本正确性;
- 数据1:随机数据,String 长度为 105,Pattern 长度为 10;
- 数据2:随机数据,String 长度为 105,Pattern 长度为 102;
- 数据3:随机数据,String 长度为 105,Pattern 长度为 103;
- 数据4:随机数据,String 长度为 105,Pattern 长度为 104;
- 数据5:String 长度为 106,Pattern 长度为 105;测试尾字符不匹配的情形;
- 数据6:String 长度为 106,Pattern 长度为 105;测试首字符不匹配的情形。
输入格式:
输入第一行给出 String,为由英文字母组成的、长度不超过 106 的字符串。第二行给出一个正整数 N(≤ 10),为待匹配的模式串的个数。随后 N 行,每行给出一个 Pattern,为由英文字母组成的、长度不超过 105 的字符串。每个字符串都非空,以回车结束。
输出格式:
对每个 Pattern,按照题面要求输出匹配结果。
输入样例:
abcabcabcabcacabxy 3 abcabcacab cabcabcd abcabcabcabcacabxyz
输出样例:
abcabcacabxy
Not Found
Not Found
解题思路
这里给出多种解法。
首先是用库函数strstr,AC代码如下:
1 #include <cstdio> 2 #include <cstring> 3 4 const int MAXN = 1e6 + 1; 5 6 int main() { 7 char str[MAXN], pat[MAXN]; 8 scanf("%s", str); 9 int n; 10 scanf("%d", &n); 11 for (int i = 0; i < n; i++) { 12 scanf("%s", pat); 13 char *ret = strstr(str, pat); 14 printf("%s\n", ret ? ret : "Not Found"); 15 } 16 }
接着是KMP算法,AC代码如下:
1 #include <cstdio> 2 #include <cstring> 3 4 const int MAXN = 1e6 + 1; 5 6 void getNext(char *pat, int *next) { 7 next[0] = -1; 8 int m = strlen(pat); 9 for (int i = 1; i < m; i++) { 10 int j = next[i - 1]; 11 while (j != -1 && pat[j] != pat[i - 1]) { 12 j = next[j]; 13 } 14 next[i] = j + 1; 15 } 16 } 17 18 int KMP(char *str, char *pat) { 19 int n = strlen(str), m = strlen(pat); 20 int next[m]; 21 getNext(pat, next); 22 23 int i = 0, j = 0; 24 while (i < n && j < m) { 25 if (j == -1 || str[i] == pat[j]) i++, j++; 26 else j = next[j]; 27 } 28 29 return j == m ? i - j : -1; 30 } 31 32 int main() { 33 char str[MAXN], pat[MAXN]; 34 scanf("%s", str); 35 int n; 36 scanf("%d", &n); 37 for (int i = 0; i < n; i++) { 38 scanf("%s", pat); 39 int ret = KMP(str, pat); 40 printf("%s\n", ret == -1 ? "Not Found" : str + ret); 41 } 42 43 return 0; 44 }
其中getNext函数还可以写成这样:
1 void getNext(char *pat, int *next) { 2 next[0] = -1; 3 int m = strlen(pat); 4 for (int i = 0, j = -1; i < m - 1; ) { 5 if (j == -1 || pat[i] == pat[j]) next[++i] = ++j; 6 else j = next[j]; 7 } 8 }
关于getNext函数的解析,可以参考我的博客,KMP算法中我对获取next数组的理解:https://www.cnblogs.com/onlyblues/p/14829122.html
最后给个用STL中的std::string实现的AC代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <string> 4 using namespace std; 5 6 void getNext(string &pat, int *next) { 7 next[0] = -1; 8 for (int i = 0, j = -1; i < pat.size() - 1; ) { 9 if (j == -1 || pat[i] == pat[j]) next[++i] = ++j; 10 else j = next[j]; 11 } 12 } 13 14 int KMP(string &str, string &pat) { 15 int n = str.size(), m = pat.size(); 16 int next[m]; 17 getNext(pat, next); 18 19 int i = 0, j = 0; 20 while (i < n && j < m) { 21 if (j == -1 || str[i] == pat[j]) i++, j++; 22 else j = next[j]; 23 } 24 25 return j == m ? i - j : -1; 26 } 27 28 int main() { 29 string str, pat; 30 getline(cin, str); 31 int n; 32 scanf("%d\n", &n); 33 for (int i = 0; i < n; i++) { 34 getline(cin, pat); 35 int ret = KMP(str, pat); 36 printf("%s\n", ret == -1 ? "Not Found" : str.c_str() + ret); 37 } 38 39 return 0; 40 }
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/14828944.html