-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path12_KMP.cpp
148 lines (139 loc) · 3 KB
/
12_KMP.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
* P455 KMP 算法
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
// 主串
string text;
// 模式串
string pattern;
// next array
int *nextArray;
void init()
{
cout << "Input the text string: ";
cin >> text;
cout << "Input the pattern string: ";
cin >> pattern;
// initialize next array
nextArray = new int[pattern.length()];
}
// 计算 next 数组
void calNext(int *next, string &pattern)
{
// 回溯指针
// 也可以表示最长前缀长度
int j = -1;
// 默认 next[0] = -1
next[0] = -1;
for (int i = 1; i < pattern.length(); i++)
{
// 当正在匹配的字符 p[i]
// 与正在匹配的最长前缀的下一位 p[j + 1]
// 匹配失败时,
// j 回溯到最长前缀的上一个最长前缀
while (j != -1 && pattern[i] != pattern[j + 1])
{
j = next[j];
}
// 匹配成功
// 最长前缀 + 1
if (pattern[i] == pattern[j + 1])
{
j += 1;
}
next[i] = j;
}
}
// KMP
// 返回匹配成功的下标
int KMP(string &text, string &pattern)
{
int next[pattern.length()];
// 计算 next 数组
calNext(next, pattern);
int j = -1;
// 开始匹配
for (int i = 0; i < text.length(); i++)
{
while (j != -1 && text[i] != pattern[j + 1])
{
j = next[j];
}
if (text[i] == pattern[j + 1])
{
j++;
}
// 当 j 匹配到模式串最后一位
// 匹配成功
if (j == pattern.length() - 1)
{
return i - j;
}
}
// 匹配失败
return -1;
}
// KMP + pattern出现次数
int calKMPCount()
{
int result = 0;
int j = -1;
for (int i = 0; i < text.length(); i++)
{
while (j != -1 && text[i] != pattern[j + 1])
{
j = nextArray[j];
}
if (text[i] == pattern[j + 1])
{
j++;
}
// succeeded
if (j == pattern.length() - 1)
{
result += 1;
// j pointer 回溯
j = nextArray[j];
}
}
return result;
}
// print
void printNext()
{
cout << "Next array: " << endl;
for (int i = 0; i < pattern.length(); i++)
{
cout << nextArray[i] << " ";
}
cout << endl;
}
int main()
{
init();
calNext();
printNext();
/*
if (KMP())
{
cout << "Match succeeded. " << endl;
}
else
{
cout << "Match failed. " << endl;
}
*/
int count = calKMPCount();
if (count != 0)
{
cout << "Match succeeded. \nTotal appears " << count << " times. " << endl;
}
else
{
cout << "Match failed. " << endl;
}
return 0;
}