算法思想
next数组
不含当前,前面字符串的前后缀最大匹配长度(不为整体),0下表的next为-1
a abaabsaabaaa
-1 0 1
aab
“” “” √ 长度0
a b × 长度1
aa ab× 长度2
可补终止位置的next值
程序实现
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
| public static int kmp(char[] s1, char[] s2){ int n = s1.length, m = s2.length,x = 0, y = 0; int[] next = nextArray(s2, m); while (x < n && y < m){ if (s1[x] == s2[y]){ x++; y++; } else if (y == 0){ x++; } else { y = next[y]; } } return y == m ? x - y : -1; }
public static int[] nextArray(char[] s,int m){ if(m == 1){ return new int[] {-1}; } int[] next new int[m]; next[0] = -1; next[1] = 0; int i = 2, cn = 0; while (i < m){ if (s[i - 1] == s[cn]){ next[i++] = ++cn; } else if (cn > 0){ cn = next[cn]; } else { next [i++] = 0; } } }
|
时间复杂度分析
生成next的数组过程中,
if:i++,i-cn不变
else if:i不变,i-cn增加
else:i++,i-cn增加
因为i<m,i-cn<m,所以总复杂度<O(2m),所以生成next的复杂度为O(m)
KPM过程中:
if:x++,x-y不变
else if: x++,x-y增加
else:x不变,x-y增加
x<n,x-y<n,复杂度<O(2n),O(nS)
例题
判断子树
有两棵二叉树root和subRoot,检验root中是否包含和subRoot具有相同结构和结点的子树,如果存在返回ture,否则返回false
方法一:暴力递归O(n*m)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public static boolean isSubtree(TreeNode t1, TreeNode t2){ if(t1 != null && t2 != null){ return same(t1, t2)||isSubtree(t1.left, t2)||isSubtree(t1.right, t2); } return t2 == null; }
public static boolean same(TreeNode a, TreeNode b){ if(a == null && b == null){ return true; } if(a != null && b != null){ return a.val == b.val && same(a.left, b.left) && same(a.right, b.right); } }
|
方法二:二叉树先序序列化+KMP算法匹配O(n+m)
判断t2序列化后是否为t1序列化后的子串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public static boolean isSubtree2(TreeNode t1, TreeNode t2){ if(t1 != bull && t2 != null){ ArrayList<String> s1 = new ArrayList<>(); ArrayList<String> s2 = new ArrayList<>(); serial(t1, s1); serial(t2, s2); return kmp(s1, s2) != -1; } return t2 == null; }
public static void serial(TreeNode head, ArrayList<String> path){ if(head == null){ path.add(null); } else{ path.add(String.valueOf(head.val)); serial(head.left, path); serial(head.right, path); } }
|