串的模式匹配

串的模式匹配

给定两个由英文字母组成的字符串 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 }

posted @ 2021-05-30 21:06  onlyblues  阅读(471)  评论(0编辑  收藏  举报
Web Analytics