每一层 search 中,参数里面的 start / end / n 代表着相对于原始 string 的位置,用于查询和记录 DP; 而这一层的 s1, s2 又是新的子问题,除了涉及传参和DP之外的地方,都以 s1, s2 为准。
s.substring(i,j) 中,最后截取的 substring 长度就是 j - i.
publicclassSolution {publicbooleanisScramble(String s1,String s2) {if(!isAnagram(s1, s2)) returnfalse;int n =s1.length();// dp[i][j][k] : s1 starting from index i, s2 string from index j// pick k chars, are we getting scrambled strings ?// 0 : not searched, 1 : true, -1 : false;int[][][] dp =newint[n][n][n +1];returnisScrambleMemo(s1, s2,0,0, n, dp); }privatebooleanisScrambleMemo(String s1,String s2,int oneStart,int twoStart,int n,int[][][] dp){if(dp[oneStart][twoStart][n] !=0) return (dp[oneStart][twoStart][n] ==1) ?true:false;if(s1.equals(s2)){ dp[oneStart][twoStart][n] =1;returntrue; }if(!isAnagram(s1, s2)){ dp[oneStart][twoStart][n] =-1;returnfalse; }// i = number of characters we takefor(int i =1; i <s1.length() ; i++){String s1Left =s1.substring(0, i);String s1Right =s1.substring(i,s1.length());String leftSideS2Left =s2.substring(0, i);String leftSideS2Right =s2.substring(i,s2.length());String rightSideS2Left =s2.substring(0,s2.length() - i);String rightSideS2Right =s2.substring(s2.length() - i,s2.length());if(isScrambleMemo(s1Left, leftSideS2Left, oneStart, twoStart, i, dp)&&isScrambleMemo(s1Right, leftSideS2Right, oneStart + i, twoStart + i, n - i, dp)) { dp[oneStart][twoStart][n] =1;returntrue; }if(isScrambleMemo(s1Left, rightSideS2Right, oneStart, twoStart + n - i, i, dp)&&isScrambleMemo(s1Right, rightSideS2Left, oneStart + i, twoStart, n - i, dp)) { dp[oneStart][twoStart][n] =1;returntrue; } } dp[oneStart][twoStart][n] =-1;returnfalse; }// Assuming only lower case lettersprivatebooleanisAnagram(String s1,String s2){if(s1.length() !=s2.length()) returnfalse;int[] hash =newint[26];for(int i =0; i <s1.length(); i++){int index =s1.charAt(i) -'a'; hash[index] ++; }for(int i =0; i <s2.length(); i++){int index =s2.charAt(i) -'a'; hash[index] --;if(hash[index] <0) returnfalse; }returntrue; }}