今天学习了KMP算法,试着练习写了一段代码验证算法的过程与实现,代码如下:
计算 next 数组:
public static void getNext(char[] pattern, int[] next) {
int len = pattern.length;
next[0] = 0;
for(int i = 1, k = 0; i < len; i ++) {
while(k > 0 && pattern[k] != pattern[i]) {
k = next[k - 1];
}
if(pattern[k] == pattern[i]) {
k ++;
}
next[i] = k;
}
}
public static void kmp(String target, String pattern, ArrayList<Integer> res) {
if( target != null && pattern != null && target.length() != 0
&& pattern.length() != 0) {
char[] t = target.toCharArray();
char[] p = pattern.toCharArray();
int lt = t.length;
int lp = p.length;
int i = 0;
int j = 0;
int[] next = new int[lp];
getNext(p, next); // 获取 next 数组
while(i - j <= lt - lp) {
if(p[j] == t[i]) {
i ++;
j ++;
if(j == lp) {
res.add(i - j); // 记录每个子字符串出现的起始位置
j = next[j - 1];
}
} else {
if(j == 0) { // j == 0 表示 parttern第一个字符都不匹配, 向后平移一个字符单位
i ++;
} else {
j = next[j - 1];
}
}
}
}
}
测试:
public static void main(String[] args) {
// TODO Auto-generated method stub
String target = "bbc abcdab abcdabcdabcfe";
String pattern = "abcda";
ArrayList<Integer> res = new ArrayList<Integer>();
MyString.kmp(target, pattern, res);
if(res.size() > 0) {
System.out.println("字符串 \"" + target + "\" 中总共有 "
+ res.size() + " 个 \"" + pattern + "\" 子字符串,他们分别位于:\n");
for(Integer i : res) {
System.out.println("\"" + target + "\" " + "的第 "
+ (i + 1) + " 个字母到第 " + (i + pattern.length()) + " 个字母");
}
} else {
System.out.println("字符串 \"" + target + "\" 中不包含 \"" + pattern + "\" 字符串");
}
}
测试结果:
学习参考的连接: