それを正しく理解するには、ダイアグラムを注意深く見て、グラフを読みながら再帰的な上から下へのアプローチに従ってください。
Here, xstr = "ABCD"
ystr = "BAEC"
lcs("ABCD", "BAEC") // Here x != y
/ \
lcs("BCD", "BAEC") <-- x==y --> lcs("ABCD", "AEC") x==y
| |
| |
lcs("CD", "AEC") <-- x!=y --> lcs("BCD", "EC")
/ \ / \
/ \ / \
/ \ / \
lcs("D","AEC") lcs("CD", "EC") lcs("BCD", "C")
/ \ / \ / \
lcs("", "AEC") lcs("D","EC") lcs("CD", "C") lcs("BCD","")
| \ / \ | / |
Return lcs("", "EC") lcs("D" ,"C") lcs("D", "") lcs("CD","") Return
/ \ / \ / \ / \
Return lcs("","C") lcs("D","") lcs("","") Return lcs("D","") Return
/ \ / \ / / \
Return lcs("","") Return lcs("", "") Return
| |
Return Return
注: 再帰呼び出しの適切な表現方法は通常、ツリー アプローチを使用して行われますが、ここではツリーを圧縮するためだけにグラフ アプローチを使用して、再帰呼び出しを簡単に理解できるようにしました。そしてもちろん、私が表現するのは簡単です。
上の図では、 inからとinからlcs("CD", "EC")
を削除した結果のような冗長なペアがいくつかあります。その結果、これらのペアは実行中に複数回呼び出され、プログラムの時間の複雑さが増します。"A"
"AEC"
lcs("CD", "AEC")
"B"
"BCD"
lcs("BCD", "EC")
空の文字列またはx==y
. したがって、文字列の長さが n の場合、m (xstr の長さと ystr の長さをn
考慮m
して、最悪のシナリオを考えています)です。次に、順序の最後に2 n+mという数の結果があります。(どう?と思う)
n+mは整数なので、Nとしましょう。したがって、アルゴリズムの時間計算量はO(2 N )であり、これはNの値が大きい場合には効率的ではありません。
したがって、再帰的アプローチよりも動的プログラミングアプローチを優先します。n == m の場合、時間の複雑さをO(nm) => O(n 2 )に減らすことができます。
今でも、ロジックを理解するのに苦労している場合は、tree-like
(ここに示したグラフではなく)xstr = "ABC"
との表現を作成することをお勧めしますystr = "EF"
。ご理解いただければ幸いです。
ご不明な点がございましたら、コメントをお待ちしております。