package com.interview.books.leetcodeoj;
/**
* Created_By: stefanie
* Date: 14-12-19
* Time: 上午10:18
*/
public class LOJ28_SubstringMatching {
//Naive solution: for every position of str, try to check if it can match pattern. O(N^2).
//KMP: optimize by minimize the backtracing in str, str only go forward, and pattern backtracing to least using next[].
// next[] is calculate based on the longest suffix equals to prefix.
//basic process: match str.charAt(i) and pattern.charAt(j),
// if match both move towards, and check if already visit to the end of pattern
// if not match, if j == 0, just need move i forward, if j != 0, move j to next[j]
//calNext: init next[0] = next[1] = 0;
// for other i, init j = next[i-1], and match pattern.charAt(j) and pattern.charAt(i-1)
// if match, next[i] = j + 1;
// if not match, if j == 0, next[i] = 0; if j != 0, move j to next[j];
public int strStr(String str, String pattern) {
if(pattern == null || pattern.length() == 0) return 0;
if(str == null || str.length() == 0) return -1;
int[] next = calNext(pattern);
int i = 0; int j = 0;
while(i < str.length()){
if(str.charAt(i) == pattern.charAt(j)){
i++;
j++;
if(j == pattern.length()) return i - j;
} else if(j == 0) i++;
else j = next[j];
}
return -1;
}
private int[] calNext(String pattern){
int[] next = new int[pattern.length() > 2? pattern.length() : 2];
next[0] = 0; next[1] = 0;
for(int i = 2; i < pattern.length(); i++){
int j = next[i-1];
while(true){
if(pattern.charAt(j) == pattern.charAt(i-1)){
next[i] = j + 1;
break;
} else if(j == 0){
next[j] = 0;
break;
} else j = next[j];
}
}
return next;
}
public static void main(String[] args){
LOJ28_SubstringMatching matcher = new LOJ28_SubstringMatching();
System.out.println(matcher.strStr("ABABABAC", "ABABAC"));
}
}