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).
No comments:
Post a Comment