KMP算法

KMP算法:

算法源自:

https://www.bilibili.com/video/BV1Px411z7Yo?share_source=copy_web

https://www.bilibili.com/video/BV1hW411a7ys?share_source=copy_web

 1 #include <string>
 2 #include <vector>
 3 #include <algorithm>
 4 #include <iostream>
 5 using namespace std;
 6 
 7 class Solution
 8 {
 9 public:
10     // 生成前缀表
11     void GeneratePerfixTable(string pattern, vector<int> &prefixTable) {
12         prefixTable[0] = 0;
13         int len = 0; // 相等前后缀最大长度
14         int i = 1;
15         int n = pattern.size();
16         while (i < n) {
17             // 如果当前位置字符与相等前后缀最大长度位置字符相同,则相等前后缀最大长度增加
18             // 填写当前匹配位置对应前缀表中的值为len,让i++继续匹配下个字符
19             if (pattern[i] == pattern[len]) {
20                 len++;
21                 prefixTable[i] = len;
22                 i++;
23             } else {
24                 // 匹配失败时
25                 if (len > 0) {
26                     len = prefixTable[len - 1];
27                 } else {
28                     prefixTable[i] = len;
29                     i++;
30                 }
31             }
32         }
33     }
34     // 第一个前缀表值转换为-1
35     void ShiftPrefixTable(vector<int> &prefixTable) {
36         int n = prefixTable.size();
37         for (int i = n - 1; i > 0; i--) {
38             prefixTable[i] = prefixTable[i - 1];
39         }
40         prefixTable[0] = -1;
41     }
42     // 打印前缀表
43     void PrintPrefixTable(const vector<int> &prefixTable) {
44         for (const auto &val : prefixTable) {
45             cout << val << " ";
46         }
47         cout << endl;
48     }
49     int Kmp(string text, string pattern) {
50         int m = text.size();
51         int n = pattern.size();
52         if ((m == 0) || (n == 0) || m < n) {
53             return -1;
54         }
55         vector<int> prefixTable(n);
56         GeneratePerfixTable(pattern, prefixTable);
57         ShiftPrefixTable(prefixTable);
58         PrintPrefixTable(prefixTable);
59 
60         int i = 0;
61         int j = 0;
62         while (i < m) {
63             // 如果模式串匹配到最后一个字符且与文本串中字符相同,则找到文本串中存在相同的模式串
64             if ((j == n - 1) && text[i] == pattern[j]) {
65                 return i - j;
66                 // j = pattern[j]; // 如果需要找出所有匹配的模式串位置
67             }
68             if (text[i] == pattern[j]) {
69                 i++;
70                 j++;
71             } else {
72                 // 匹配不到,则回溯到上次已匹配成功的位置
73                 j = prefixTable[j];
74                 if (j == -1) {
75                     i++;
76                     j++;
77                 }
78             }
79         }
80         return -1;
81     }
82 };
83 
84 int main()
85 {
86     Solution *test = new Solution();
87     string text = "ABABABCABAABABABABA";
88     string pattern = "ABABCABAA";
89     // KMP算法找到文本串中包含模式串的首次位置
90     cout << test->Kmp(text, pattern) << endl; // 1
91     system("pause");
92     return 0;
93 }

运行效果:

 

posted @ 2022-03-16 00:49  跳动的休止符  阅读(32)  评论(0)    收藏  举报