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
import java.util.*;

class Program {
public static boolean knuthMorrisPrattAlgorithm(String string, String substring) {
int[] pattern = buildPattern(substring);
return doesMatch(string, substring, pattern);
}

public static int[] buildPattern(String substring) {
int[] pattern = new int[substring.length()];
Arrays.fill(pattern, -1);
int j = 0, i = 1;
while (i < substring.length()) {
if (substring.charAt(i) == substring.charAt(j)) {
pattern[i] = j;
i += 1;
j += 1;
} else if (j > 0) {
j = pattern[j - 1] + 1;
} else {
i += 1;
}
}
return pattern;
}

public static boolean doesMatch(String string, String substring, int[] pattern) {
int i = 0, j = 0;
while (i + substring.length() - j <= string.length()) {
if (string.charAt(i) == substring.charAt(j)) {
if (j == substring.length() - 1)
return true;
i += 1;
j += 1;
} else if (j > 0) {
j = pattern[j - 1] + 1;
} else {
i += 1;
}
}
return false;
}
}

经典算法KMP.

下面是比较好理解的一个版本.

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
package com.interview.string;

/**
* Date 09/22/2014
* @author tusroy
*
* Do pattern matching using KMP algorithm
*
* Runtime complexity - O(m + n) where m is length of text and n is length of pattern
* Space complexity - O(n)
*/
public class SubstringSearch {

/**
* Compute temporary array to maintain size of suffix which is same as prefix
* Time/space complexity is O(size of pattern)
*/
private int[] computeTemporaryArray(char[] pattern){
int [] lps = new int[pattern.length];
int index =0;
for(int i=1; i < pattern.length;){
if(pattern[i] == pattern[index]){
lps[i] = index + 1;
index++;
i++;
}else{
if(index != 0){
index = lps[index-1];
}else{
lps[i] =0;
i++;
}
}
}
return lps;
}

/**
* KMP algorithm of pattern matching.
*/
public boolean KMP(char[] text, char[] pattern){

int lps[] = computeTemporaryArray(pattern);
int i=0;
int j=0;
while(i < text.length && j < pattern.length){
if(text[i] == pattern[j]){
i++;
j++;
}else{
if(j!=0){
j = lps[j-1];
}else{
i++;
}
}
}
if(j == pattern.length){
return true;
}
return false;
}

public static void main(String args[]){

String str = "abcxabcdabcdabcy";
String subString = "abcdabcy";
SubstringSearch ss = new SubstringSearch();
boolean result = ss.KMP(str.toCharArray(), subString.toCharArray());
System.out.print(result);

}
}