文字列s1を考えると、我々は再帰的に二つの非空部分文字列にそれを分割することによって、バイナリツリーとしてそれを表すことができます。
以下は、S1 =「素晴らしい」の一つの可能な表現は次のとおりです。
great
/
GR食べる
/ \ /
でGRE
/
で
文字列をスクランブルするために、我々はすべての非リーフノードを選択し、その2人の子供を交換します。
我々はノード「GR」を選択し、その2人の子供を入れ替えた場合、それはスクランブル文字列「rgeat」を生成します。
rgeat
/
RG食べる
/ \ /
でRGE
/
で
私たちは、「rgeat」は「偉大な」のスクランブル文字列であると言います。
同様に、我々は、ノードの子供を交換し続けた場合、「食べる」と「で」は、それがスクランブル文字列「rgtae」を生成します。
rgtae
/
RG TAE
/ \ /
RG電子TA
/
TA
私たちは、「rgtae」は「偉大な」のスクランブル文字列であると言います。
s2がS1のスクランブル文字列の場合は二つの文字列s1とs2同じ長さを考えると、決定します。
例1:
入力:S1 =「素晴らしい」、S2 =「rgeat」
出力:真の
例2:
入力:S1 =「ABCDE」、S2 =は「caebd」
出力:偽
func isScramble(s1 string, s2 string) bool {
if len(s1) != len(s2) {
return false
}
if s1==s2 {
return true
}
lg := len(s1)
dp := make([][][]bool, lg)
for i := 0; i < lg; i++ {
dp[i] = make([][]bool,lg)
for j := 0; j < lg; j++ {
dp[i][j] = make([]bool,lg+1)
dp[i][j][1] = s1[i]==s2[j]
}
}
for l := 2; l <= lg; l++ {
for i := 0; i <= lg-l; i++ {
for j := 0; j <= lg-l; j++ {
for k := 1; k < l; k++ {
if (dp[i][j][k] && dp[i+k][j+k][l-k]) || (dp[i][j+l-k][k] && dp[i+k][j][l-k]) {
dp[i][j][l] = true
break
}
}
}
}
}
return dp[0][0][lg]
}