開始文字と終了文字が一致する単語の最長リスト


11

私の友人は、彼が簡単だと言っている問題を私に与えましたが、私はそれをするのに使う良いアルゴリズムを見つけられません。

100個のランダムな英語の単語が入力されます。ある単語の最後の文字が次の単語の最初の文字と一致する単語の最も長い文字列を見つける必要があります。各単語は1回しか使用できません。

たとえば、「cat」、「dog」、「that」という単語を指定した場合、作成できる最長の文字列は「cat-> that」になります。「マウス」、「ムース」、「ユニコーン」という単語が与えられた場合、作成できる最長の文字列は1つの単語になります(これらの単語はリンクしていないため)。「鳥」、「皿」、「港」という単語が与えられた場合、作成できる最長の文字列は「港->鳥->皿」(または「皿->港->鳥」または「鳥- >皿->ハーブ」)。

これを有向巡回グラフとしてモデル化するというアイデアを思いつきました。各ノードは単なる単語であり、頂点はこの単語が終わる文字で始まる各単語/ノードに移動します。

+-------+         \ +------+
|  cat  |-----------| that |
+-------+         / +------+
    |                  |
   \|/                 |
+-------+ /            |
|  the  |--------------+
+-------+ \

この問題は、NP-Hardである最長パス検索のようです。

それを行うより良い方法はありますか?または、使用できる近似アルゴリズムのようなものもありますか?または、検索スペースを削減するために英語の資質を活用する方法はありますか?


4
100語で、(少なくとも)100が得られます!= 9.332622e + 157の組み合わせ。幸運を祈ります。あなたの友人はこれを簡単に言って足を引っ張っていると思います。
マーティンウィックマン

1
ただし、可能な組み合わせの数はそれよりもはるかに少なくなります。これは、平均して1つの単語が約6個または7個の他の単語にのみリンクされているためです。
安倍ツール

2
これが正確に最長パス検索であることは正しいです。あなたの友人は間違っていると思います。ただし、徹底的な検索はコーディングするのが難しくなく、それほど長く実行されるとは限りません。
ケビンクライン

4
楽しみのために、Ruby(gist.github.com/anonymous/6225361)でブルートフォースの徹底的な検索(@kevinclineが指摘したとおり)をコーディングしました。100ワードで、わずか96秒しかかかりません(gist.github.com/anonymous/6225364)。そして、これは非常に非効率的で、最適化されていない、解釈された言語の、迅速で汚いスクリプトでした。そのため、100語のみで、ブルートフォースの低速バージョンでも同じ時間内に実行されます。私のコードは実際に非循環グラフを作成してから検索するのではなく、各単語から始まるすべての可能なパスを再帰的に構築し、最も長いものを追跡します。
ベン・リー

3
問題は、100語があることを示しています。これは、ダイナミックプログラミングソリューションを適用できることを意味すると思います。これについては、言及している記事に記載されています。
ジュリアンゲルトー

回答:


5

これはあなたが言及した最長パス(LP)の問題に関連していると思いますが、少し異なります。主な違いは、LPの問題の方が、提案されている問題よりも接続性が高いことです。接続を最後の文字と最初の文字に制限することにより、多数の潜在的な組み合わせを削除します。

これに取り組むことをお勧めします。

  1. リスト内の各単語について、可能な接続の数と接続の数を数えます。
  2. 0個のインと0個のアウトがある単語はすべて破棄します。
  3. インとアウトの数が最も少ない「スターターワード」の初期セットを特定します。アウトは0より大きくなければなりません。
  4. 各スターターワードは、ins / outs接続カウントの独自の作業コピーを受け取ります。これがチェーンの頭を形成します。
  5. 各チェーンについて、次に基づいて「次の単語」のリストを識別します。
    • スターターの最後の文字または前の単語
    • 入力および出力接続の最小数(繰り返しますが、出力は0より大きくなければなりません)
  6. それぞれについてnext word、チェーンが終了するまで手順5を繰り返します。

それを念頭に置いて:

  • チェーンの長さを追跡し、最長のチェーンを識別するためのグローバルなメカニズムが必要になります。

  • また、再帰ループを回避するために、接続カウントの作業コピーから各単語を削除する必要があります。

  • ある時点で、チェーンは終了し、接続数が0の単語を選択する必要があります。

  • 作業リストから単語が削除されると、ins / outsを再計算する必要がある場合があります。一見したところ、全体のセットが比較的小さいため、これが必要になるとは思いません。1000ワードにスケールアウトした場合、静的カウントを使用すると、アルゴリズムの収束が遅くなる可能性があります。

これは梱包の問題だと思っていました。私にとって、出入りする接続は、梱包する形状を識別します。接続が低いほど、形状が奇妙になります。奇形が奇妙であればあるほど、奇異な形を詰め込めるオッズが減っていると感じたので、より早くそれを詰めたいと思います。

例として:

{dog, gopher, alpha, cube, elegant, this, that, bart}

dog     0, 1
gopher  1, 0
alpha   0, 0
cube    0, 1
elegant 1, 2
this    3, 0
that    2, 1
bart    0, 2

//alpha is dropped with 0 in and 0 out.
//two candidates found: dog, cube

//chain 1
dog => gopher
//chain 2
cube => elegant => that => this

//Note 1: the following chain won't occur due to selection rules
//that takes priority over this because of output count
cube => elegant => this

//Note 2: this chain won't occur either due to selection rules
bart => that => this

2
このアルゴリズムが常に最長パスを見つけるという保証はありますか?私の頭上では、反例を考えることはできませんが、これは「極大」タイプのソリューションに当てはまるかもしれません。
ベン・リー

@BenLee-私はソフトウェアエンジニアです。コードを保証することはありません。:-)しかし、真剣に、私はあなたの質問に対する答えを知りません。私のセット理論と数学的な証明スキルは弱く、弱いので、アルゴリズムを検証するための経験的評価以外の方法はありません。この問題が本当にNP困難なのかはわかりませんが、その主張を検証することもできません。NPハードでない場合は、アルゴリズムを検証する手段が必要です。

2
「犬、ホリネズミ、お団子、修道女、正午、nub」などの単語リストについてはどうでしょう。アルゴリズムは、実際には「bun、nun、noon、nub」の任意の組み合わせである場合、「dog-> gopher」として最長リストを誤って選択します。
安倍ツール

1
@AbeTool-良い例です。「最低入力> = 1」と「最低出力> = 1」の組み合わせを可能にするために、別の反復(または2つ)を追加します。

2
それがすべてのケースで問題を解決するとは思わない。これは「極大」タイプのソリューションに該当すると思います。
安倍ツール

3

26X26マトリックスを作成して、頂点の有向グラフを各アルファベットとして表し、単語をエッジとして表す場合。たとえば、APPLEは頂点AとEをAからEに向けられたエッジに接続します。問題は、グラフで最大のオイラー軌跡(エッジの最大数を含むパス、頂点の可能な繰り返しで各エッジを訪れる)を見つけることになります。O(E)アルゴリズムの1つは、頂点のペアからランダムに開始することです。それらの間のパスを見つけます。それが可能になるまでパスをリラックスし続けるよりも。

update @ GlenH7最近www.hackerearth / jdaで同様の質問を解決しました。最良の解決策に関して相対的なマークがあり、次のアプローチで最高のマークを獲得しました。

与えられた単語のリスト。それらによって形成できる最長のチェーンを見つけてください。すべての単語が*最後の単語の終わりで終わる文字で始まる場合、チェーンは有効です。

アプローチ=

1)アルファベットを頂点としてグラフ化し、単語をエッジとして作成します。複数のエッジを使用する代わりに、エッジの数に等しい重みを持つエッジを使用します。

2)最大のエッジを持つグラフの強く接続されたコンポーネントを見つけます。他のエッジを一時的に破棄します。

3)各頂点について、その次数をその次数に等しくします。

4)グラフにオイラー回路が存在するようになりました。それを見つける。

5)残りのグラフ(wrt orignal graphで、選択された強く連結されたコンポーネントの最初の頂点を持つ最長の軌跡を見つけます。これはNP難しいと思います。

6)オイラー回路をトレイルに変換するエレリアン回路に上記のトレイルを含める。

なぜ-この質問はおそらくNPが難しい(数学的に言えば推測ではない)と思う。ただし、上記のアプローチは、均一に分散された単語の長いリスト(1000+)がある場合に最適に機能します(つまり、上記のアプローチでwcになることを意図していません)。与えられたリストを上記のグラフに変換した後、幸運なことにオイラーグラフであることがわかりました(条件についてはhttp://en.wikipedia.org/wiki/Eulerian_pathを参照してください)、そして間違いなくその答えを言うことができます上記の質問への質問はPであり、実際にはグラフのオイラーパスです(そうするための非常に簡単なアプローチについてはhttp://www.graph-magics.com/articles/euler.phpを参照し、グラフがシングルhttp://www.geeksforgeeks.org/strongly-connected-components/オイラーパスが単一のsccに存在するため、一時的に他の小さなsccをクリーニングしない場合)。したがって、ラッキーでないケース(ほとんどすべてのケース)については、それらをラッキーなケースに変換しようとします(つまり、オイラートレイル条件が満たされます)。これを行う方法?無関係なエッジ(outdegreeがindegreeよりも大きい頂点から始まり、indegreeがoutdegreeよりも大きい頂点で終わるパス内のエッジのセット)の深さ検索を増やしてみました。深さ検索の増加は、最初にパス内の2つのエッジなどよりも、パス内の1つのエッジのそのようなセットをすべて検索することを意味します。一見、i番目の深さ検索はO(nodes ^ i)を要するため、O(nodes + nodes ^ 2 + nodes ^ 3 + ....)の合計時間の複雑さがラッキーなケースになるまでに見えるかもしれません。ただし、償却分析ではO(edges)であることがわかります。ラッキーケースが減ったら、オイラー回路を見つけてください。

ここまでは、すべて多項式時間でした。これにより、ほぼ最良のソリューションが得られます。ただし、ソリューションをさらに向上させるには(完全なソリューションはNP困難です)、残りのグラフで貪欲なアプローチを試して、選択したsccの頂点の1つを見つめる長いトレイルを見つけてください。これを上記のオイラートレイルに追加して、さらに増加させます。


GlenH7私は最近www.hackerearth / JDA上で同様の問題を解決しました@、そこに最高のソリューションとの相対的なマークがだったと私は、次のapproch-で最高点を獲得
vishfrnds

0

考え:

まず、アルファベット文字から単語までの2つのマップ(ハッシュ)、たとえばSとEを作成します。最初のSは開始文字を単語にマップし、2番目のEは終了文字に対して同じことを行います。

たとえば、辞書が次のもので構成されている場合:

鳥、皿、犬、ハーバー

我々は持っています:

S:

a -> [ ]
b -> [ bird ]
c -> [ ]
d -> [ dish, dog ]
...
h -> [ harb ]
...

そして、

E:

a -> [ ]
b -> [ harb ]
c -> [ ]
d -> [ bird ]
...
g -> [ dog ]
h -> [ dish ]
...

次に、SとEを使用して高速検索を行い、各単語にルートを持つ辞書と同じサイズのフォレスト(ツリーのセット)を作成し、ツリー内で単語が複数回表示されないようにします構築する木の深さ:

bird (depth: 2)
   dish
      harb
   dog

dish (depth: 3)
   harb
      bird
         dog

dog (depth: 0)

harb (depth: 2)
   bird
      dish
      dog

最後に、森林を反復処理して、最も深いツリーを見つけます。

ソリューションは、それらの木の子孫軸上にあります。

例えば、

dish / harb / bird / dog

上記。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.