-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathKMP
More file actions
116 lines (103 loc) · 3.42 KB
/
KMP
File metadata and controls
116 lines (103 loc) · 3.42 KB
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
class Solution {
public:
bool isMatch(string s, string p) {
//edge case
if(s == p) return true;
if(s.length() < p.length()) return false;
if(p == "") return true;
//预处理得到next数组
vector<int> next(p.length(), 0);
preProcess(p, next);
int n = s.length();
int i = 0, j = 0;
bool newBeg = false;
while(i < n) {
while(s[i] != p[j]) {
j = next[j];
if(j == -1) {
break;
}
}
i++;
j++;
if(j == p.length()) return true;
}
return false;
}
void preProcess(string s, vector<int>& next) {
next[0] = -1;
for(int i = 1; i < s.length(); i++) {
//默认从头比较
next[i] = 0;
//比较两端的最长相同子串,取最长的给到next数组
for(int j = 1; j < i; j++) {
string l = s.substr(0, j);
string r = s.substr(i-j, j);
if(l == r) next[i] = j;
}
}
}
};
// 计算next数组是一种解法, 但这里我更推荐计算lps数组 (longest proper prefix suffix)
// for example:
// 输入串 abcabdabcabc
// 模式串 abcabc
// lps 000123
// 先预处理模式串,思路为维护一个索引len, 以及当前pattern的元素索引
初始时, lps[0] = 0
然后从下标为1的元素开始求解,
假如char[i] == char[len]
那么lps[i++] = ++len;
因为我们要给i赋值, 而值应该是++len, 想想第一个元素和第二个元素相同时, lps[1] = 1
如果char[i] != char[len]
那么如果len > 0, 那么 len = lps[len - 1]
因为我们知道从0到len - 1的串 与从 i - len + 1到i 的串是相同的,
现在第len个元素和第i个元素不同, 而lps[len - 1]中记录了当地len个元素不匹配时, 应该回退到的
下标. 所以len = lps[len - 1]
当然你可能会想为什么不是len = lps[i - 1],
因为lps[i - 1]返回的是下标len, 这样会陷入死循环, 并且它并不是求解前缀和后缀匹配的长度.
class Solution {
public int strStr(String haystack, String needle) {
if (haystack == null || needle == null) return -1;
if (haystack.length() < needle.length()) return -1;
if (needle.isEmpty()) return 0;
int n = haystack.length();
int m = needle.length();
int[] los = preProcess(needle);
int i = 0, j = 0;
while (i < n && j < m) {
if (haystack.charAt(i) == needle.charAt(j)) {
++i;
++j;
if (j == m) {
return i - m;
}
} else {
if (j > 0) {
j = los[j - 1];
} else {
++i;
}
}
}
return -1;
}
private int[] preProcess(String pattern) {
int n = pattern.length();
int[] los = new int[n];
los[0] = 0;
int len = 0;
for (int i = 1; i < n;) {
if (pattern.charAt(len) == pattern.charAt(i)) {
los[i++] = ++len;
} else {
if (len > 0) {
len = los[len - 1];
} else {
los[i++] = 0;
}
}
}
return los;
}
}