Google – Multiple Strings Pattern Matching
输入一个pattern,和一堆strings,做跨string的pattern matching.
比如:
patter: "abc"
strs: "ab", "cd" => true
strs: "aa", "bcd" => true
strs: "ab", "ac" => false
strings的输入是一个iterator,只能往前,不能往后。
[Solution]
Greedy
KMP
两种方法各有利弊,greedy edge cases很多。kmp虽然简单,但是把所有strings串起来内存很可能不够。
[Solution #1] – Greedy
Greedy的解法要记住前面是否有已经匹配的,随时要判断是继续匹配前面的,还是重新开始匹配当前的。
[Solution #2] – KMP
把iterator里的所有string串起来,对pattern做kmp
Cons: 注意内存不够的情况。
[Solution #3] – KMP with Cut
但是内存不够的情况也还是有解决办法。分段处理。(前提是pattern必须得放的进内存)
比如内存只能放m个字符(这里排除了pattern所占的空间,假设除去pattern之后,还能塞m个),串起来之后的总长度为n,那么每次取m个字符和pattern来匹配,
Read full article from Google – Multiple Strings Pattern Matching
输入一个pattern,和一堆strings,做跨string的pattern matching.
比如:
patter: "abc"
strs: "ab", "cd" => true
strs: "aa", "bcd" => true
strs: "ab", "ac" => false
strings的输入是一个iterator,只能往前,不能往后。
[Solution]
Greedy
KMP
两种方法各有利弊,greedy edge cases很多。kmp虽然简单,但是把所有strings串起来内存很可能不够。
[Solution #1] – Greedy
Greedy的解法要记住前面是否有已经匹配的,随时要判断是继续匹配前面的,还是重新开始匹配当前的。
[Solution #2] – KMP
把iterator里的所有string串起来,对pattern做kmp
Cons: 注意内存不够的情况。
[Solution #3] – KMP with Cut
但是内存不够的情况也还是有解决办法。分段处理。(前提是pattern必须得放的进内存)
比如内存只能放m个字符(这里排除了pattern所占的空间,假设除去pattern之后,还能塞m个),串起来之后的总长度为n,那么每次取m个字符和pattern来匹配,
- 如果匹配成功,返回true。
- 如果完全没有匹配,把下一段m长度丢进来。
- 如果匹配了k个字符,这k个字符必须是m个字符的suffix,那么就丢掉前面(m – k)个字符,加入下一段(m – k),从pattern的k + 1位置开始继续往下匹配。
- 如果在第3种情况下,后面加入的(m – k)个字符又都被匹配成功了,那么我们可以把目前内存里所有m个字符全部丢掉,加入下一段,从pattern的m + 1位置继续往下匹配。(不需要假设pattern长度小于m)
class
Solution {
public
boolean
patternMatch(String pattern, Iterator<String> it) {
if
(pattern ==
null
|| pattern.isEmpty() || it ==
null
) {
return
false
;
}
int
prevStart =
0
;
while
(it.hasNext()) {
String curr = it.next();
int
currStart =
0
;
for
(
int
i =
0
; i < curr.length(); i++) {
char
c = curr.charAt(i);
if
(prevStart != -
1
&& currStart != -
1
&& pattern.charAt(prevStart) == c && pattern.charAt(currStart) == c) {
prevStart++;
currStart++;
}
else
if
(prevStart != -
1
&& pattern.charAt(prevStart) == c) {
prevStart++;
if
(c == pattern.charAt(
0
)) {
currStart =
1
;
}
else
{
currStart = -
1
;
}
}
else
if
(currStart != -
1
&& pattern.charAt(currStart) == c) {
currStart++;
prevStart = -
1
;
}
else
{
if
(c == pattern.charAt(
0
)) {
currStart =
1
;
}
else
{
currStart = -
1
;
}
prevStart = -
1
;
}
if
(prevStart == pattern.length() || currStart == pattern.length()) {
return
true
;
}
}
if
(prevStart == -
1
) {
prevStart = currStart;
}
}
return
false
;
}
}
class
Solution2 {
public
boolean
patternMatch(String pattern, Iterator<String> it) {
if
(pattern ==
null
|| pattern.isEmpty() || it ==
null
) {
return
false
;
}
StringBuilder sb =
new
StringBuilder();
while
(it.hasNext()) {
sb.append(it.next());
}
return
strStr(sb.toString(), pattern);
}
private
boolean
strStr(String s, String t) {
int
[] lookup = preSuffix(t);
int
i =
0
;
int
j =
0
;
while
(i < s.length()) {
if
(s.charAt(i) == t.charAt(j)) {
i++;
j++;
}
else
if
(j ==
0
) {
i++;
}
else
{
j = lookup[j];
}
if
(j == t.length()) {
return
true
;
}
}
return
false
;
}
private
int
[] preSuffix(String t) {
int
[] lookup =
new
int
[t.length()];
int
i =
1
;
int
j =
0
;
while
(i < t.length()) {
if
(t.charAt(i) == t.charAt(j)) {
lookup[i] = j +
1
;
i++;
j++;
}
else
if
(j ==
0
) {
i++;
}
else
{
j = lookup[j];
}
}
return
lookup;
}
}