web-dev-qa-db-ja.com

文字列に文字が繰り返されている可能性がある、ある文字列を別の文字列に変換するためのスワップの最小数を見つける

次の質問が突然関連しているように見えたとき、私はプログラミングの質問を調べていました。

次のように少ないスワップを使用して、文字列を別の文字列に変換するにはどうすればよいですか。文字列は相互変換可能であることが保証されています(同じ文字セットがあり、これが指定されています)、ただし、文字は繰り返すことができます。同じ質問でウェブの結果を見ましたが、文字は繰り返されていません。文字列内の任意の2文字を交換できます。

たとえば、「aabbccdd」は2回のスワップで「ddbbccaa」に変換でき、「abcc」は1回のスワップで「accb」に変換できます。

ありがとう!

19
ashu

「差分」文字列SおよびS'を作成できます。つまり、2つの文字列の異なる位置にある文字を含む文字列です。 acbacbおよびabcabcの場合、cbcbおよびbcbcになります。これにn文字が含まれているとしましょう。

これで、nノードと、S[i] == S'[j]の場合はiからjまでのエッジを持つ「順列グラフ」Gを作成できます。すべての一意の文字の場合、必要なスワップの数は(n-Gのサイクル数)であることが簡単にわかります。これは、O(n)時間。

ただし、重複する文字がいくつもある場合、これは有向グラフで最大のサイクル数を見つけるという問題になります。これは、NP困難だと思います(例:チェックアウト: http://www.math.ucsd.edu/~jverstra/dcig.pdf )。

その論文では、いくつかの欲張りアルゴリズムが指摘されており、そのうちの1つは特に単純です。

  1. 各ステップで、グラフ内の最小の長さのサイクルを見つけます(例: 正の重みを持つ有向グラフで最短の長さのサイクルを見つける
  2. 消して
  3. すべての頂点がカバーされなくなるまで繰り返します。

ただし、ケースのプロパティを利用する効率的なアルゴリズムがある場合があります(私が考えることができるのは、グラフがK-partiteになることだけです。ここで、KはS内の一意の文字の数です)。幸運を!

編集:問題のより完全で正しい説明については、Davidの回答を参照してください。

3
Subhasis Das

ハッシュマップデータ構造(重複を許可する)は、問題の解決に適しています。

文字列をs1とs2とします。アルゴリズムは文字列の両方を反復処理し、不一致が見つかると、アルゴリズムはs1の文字をs2にマップします。つまり、不一致が発生した場合は常に、s1の文字をキーとして、s2の文字を値としてハッシュマップに挿入します。

この後、結果をゼロとして初期化します。

次のステップは、ハッシュマップが空でないときに次の手順を実行することです。

  1. 任意のキーkについて、その値vを見つけます。
  2. 次に、値vをハッシュマップでルックアップするキーとして使用して、見つかった値がkに等しい場合に値を見つけ、結果を1インクリメントして、キーkとvの両方をハッシュマップから削除します。
  3. 見つかった値がkと等しくない場合は、ハッシュマップからキーkのみを削除し、結果をインクリメントします。

結果は、希望する出力を保持します。

1
akashchandrakar

ある文字列から別の文字列への同等の文字列のグラフを通る最短パスについて、A *検索を実行します(説明については http://en.wikipedia.org/wiki/A-star_search_algorithm を参照)。コストヒューリスティックとしてレーベンシュタイン距離/ 2を使用します。

1
btilly