Saturday, July 12, 2014

[Leetcode] Scramble String

Problem

Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great":
    great
   /    \
  gr    eat
 / \    /  \
g   r  e   at
           / \
          a   t
To scramble the string, we may choose any non-leaf node and swap its two children.
For example, if we choose the node "gr" and swap its two children, it produces a scrambled string "rgeat".
    rgeat
   /    \
  rg    eat
 / \    /  \
r   g  e   at
           / \
          a   t
We say that "rgeat" is a scrambled string of "great".
Similarly, if we continue to swap the children of nodes "eat" and "at", it produces a scrambled string "rgtae".
    rgtae
   /    \
  rg    tae
 / \    /  \
r   g  ta  e
       / \
      t   a
We say that "rgtae" is a scrambled string of "great".
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

Algorithm

Clarification: a string can be divided into two non-empty substrings, not equally divided into two halves. 
Only when s1 and s2 has the same length, they might be scrambled strings.  
Consider substrings of length L, start with index i in s1, and start with index j in s2. If both substrings are the same, they are scrambled strings, and we are done. Otherwise, they can be cut at l-1 positions, and have 2*(l-1) possible comparison (since we can pair left of s1 with right of s2). Recursively, 
isScramble(String s1, String s2, int i, int j, in l){
    if(i > j) return true;
    if(s1.substring(i,i+l).equals(s2.substring(j,j+l)))
        return true;
    for(int k=1;k<l;k++){
        if((isScramble(s1,s2,i,j,k) && isScramble(s1,s2,i+k,j+k,l-k)) || 
           (isScramble(s1,s2,i,j+l-k,k) && isScramble(s1,s2,i,j+k,l-k)))
    }
Note, some subproblems are solved repeatedly, we can use the memorization of DP. 
Let dp[i][j][l]  indicate whether s1.substring(i,i+k) is a scramble string of s2.substring(j,j+l)

dp[i][j][l] = true,                                                             if s1.substring(i,i+k) == s2.substring(j,j+l)
                   (dp[i][j][k] && dp[i+k][j+k][l-k])               else for k = 1:l
                   || (dp[i][j+l-k][k] && dp[i][j+k][l-k])

The running time is O(n^4). 

Code

 



No comments:

Post a Comment