import java.util.Random; public class ZFunction { // z[i] = lcp(s[0..], s[i..]) public static int[] zFunction(String s) { int[] z = new int[s.length()]; for (int i = 1, l = 0, r = 0; i < z.length; ++i) { if (i <= r) z[i] = Math.min(r - i + 1, z[i - l]); while (i + z[i] < z.length && s.charAt(z[i]) == s.charAt(i + z[i])) ++z[i]; if (r < i + z[i] - 1) { l = i; r = i + z[i] - 1; } } return z; } // random tests public static void main(String[] args) { Random rnd = new Random(1); for (int step = 0; step < 10_000; step++) { String s = getRandomString(rnd, 100); String pattern = getRandomString(rnd, 5); int pos1 = find(s, pattern); int pos2 = s.indexOf(pattern); if (pos1 != pos2) throw new RuntimeException(); } } static int find(String s, String pattern) { int[] z = zFunction(pattern + "\0" + s); for (int i = pattern.length() + 1; i < z.length; i++) if (z[i] == pattern.length()) return i - pattern.length() - 1; return -1; } static String getRandomString(Random rnd, int maxlen) { int n = rnd.nextInt(maxlen) + 1; char[] s = new char[n]; for (int i = 0; i < n; i++) s[i] = (char) ('a' + rnd.nextInt(3)); return new String(s); } }