2017-11-02 4 views
1

最長プレフィックス存在を見つける:は、たとえば、文字列のリストを考えると「ランダム」の文字列のリスト上の少なくとも2つの要素

myList = ["foo", "foobar", "football", "footbag", "bar"] 

は、リスト上の少なくとも2つの文字列の最長プレフィックス存在を見つけます:

Longest prefix is "footba" present in "football" and "footbag" 

リストは入力によって塗りつぶされ、すべてが共通の接頭辞を持つわけではありません。

オプションと考えるには、プレフィックスがリストの2つの文字列にあることで十分です。複数のオプションがある場合は、最長のオプションを返す必要があります。

私は、たとえば、すべての文字列の最長の共通のプレフィックスを取得する方法を見つけることができました私の研究で

一覧:["foo_a","foo_b","foo_c","fnord"]

出力:Longest common prefix is "f"

しかし、上の文字列私のリストは同じ文字で始まらないかもしれません。

+0

は、あなたが持っているコードを表示します。それは、この問題をより具体的でより解明しやすくします。 – jpaugh

+0

私のコードは、リストを埋めるために入力を受け取り、代わりにサンプルリストを含めたので、あまり関係がないと思われる関数になります。私はまだ問題を解決するコードはありませんが、私は実際に私が得た答えを与えられた何かに取り組んでいます。できるだけ早く更新する – oScarDiAnno

+0

'スライディングウィンドウ(sliding window) 'を使って' prefix tries'を構築することができます。 –

答えて

1

この:あなたは、パフォーマンスを気にしない場合は最大を更新維持しながら

、あなたは単に、リスト内のすべての単語を反復処理し、残りの部分にそれら(その接頭辞)のそれぞれを比較することができます大雑把な実装であり、大規模なリストでは効率的ではありませんが、仕事が完了します。私はあなたが少し時間がある場合、言及されたプレフィックスを試してみることをお勧めしたいと思います、彼らはよりよく働くでしょう。

これは、フルサイズの単語から、2つの単語が同じプレフィックスを共有するまで、後方に機能します。単語の終わりを切り捨て、同じ単語が何回出現するかを数え、少なくとも2ならばそれを返します。

from collections import defaultdict 

def list_to_text(x): 
    x = list(map(str, x)) 
    first = '", "'.join(x[:-1]) #Join together (a, b, c) 
    if first: 
     return '" and "'.join((first, x[-1])) #Add the last element (a, b, c and d) 
    return x[0] #Return a single value if list length is 1 

def find_longest_prefix(x): 
    x_max = len(max(x, key=len)) 
    for i in range(1, x_max)[::-1]: 

     #Chop off the end of every word 
     trim = [j[:i] for j in x] 

     #Iterate through every unique value 
     result = defaultdict(list) 
     for j in set(trim): 
      result[trim.count(j)].append(j) 

     #Finish iterating if there are more than 2 words that share a prefix 
     highest_count = max(result) 
     if highest_count >= 2: 
      prefix = result[highest_count] 
      words = [j for k in prefix for j in x if j.startswith(k)] 
      return prefix, words 

myList = ["foo", "foobar", "football", "footbag", "bar"] 
prefix, words = find_longest_prefix(myList) 

#Put together the string 
print('The longest common prefix{} "{}" present in "{}".'.format(' is' if len(prefix) ==1 else 'es are', 
                   list_to_text(prefix), list_to_text(words))) 

結果の数に基づいて文字列を少しフォーマットします。あなたのリストはまだこのになります:

The longest common prefix is "footba" present in "football" and "footbag". 

しかし、このようなものになります結果の同じ長さと数を持つ別の接頭辞を追加:

The longest common prefixes are "footba" and "testin" present in "football", "footbag", "testing" and "testin". 
+0

印象的です。以前は見たことのないコマンドがいくつか出てきたので、コード全体がどのように正確に動作しているかはまだ分かっていますが、何かを聞く前にそれらの一部を調べたいと思っています。 印刷機能にカッコを付けて動作させる必要がありましたが、私はすでにあなたの答えに編集を提案しました。 – oScarDiAnno

+0

ああ、私はあなたがPython 3をやっていると思います。どのように行が動いているのか理解できない場合は、私が説明するのは喜んでいるでしょうが、それはスライスと 'key = len'部分だと思います。あなたがそれをカバーしていなければ、リスト作成の仕方を理解することが重要です。他の部分は、通常Googleで簡単に見つけることができます:) – Peter

+0

はいhaha(私はPythonのバージョンを使用しました。私の質問が編集されました)。また、私は "広すぎる"との私の質問を得た。正直なところ私は例と望ましい出力を含んでいたので、なぜわからないのですか? – oScarDiAnno

2

prefix trieのフォレストを構築し、2つの(ヌル以外の)子を持つ最も深いノードの「高さ」(ルートからどれくらい離れているか)を検索できます。このノードは、最も長い共通接頭辞を表します。

def common_prefix_size(s1, s2): 
    res, i = 0, 0 
    while i < min(len(s1), len(s2)): 
     if s1[i] == s2[i]: 
      res += 1 
      i += 1 
     else: 
      break 
    return res 



def longest_prefix(lst): 
    res = '' 
    maxsize = 0 
    for i in range(len(lst) - 1): 
     for j in range(i + 1, len(lst)): 
      t = common_prefix_size(lst[i], lst[j]) 
      maxsize = max(maxsize, t) 
      if maxsize == t: 
       res = lst[i][:maxsize] 
    return res 

myList = ["foo", "foobar", "football", "footbag", "bar"] 

print(longest_prefix(myList)) # footba 
+0

私は間違いなくこれを見ていきます。私がクラスで見たことによると、私が割り当てから期待していたより少し複雑に思えます。しかし、私はそれを行う方法を理解することができ、私はそれから恩恵を受けることができると信じています。ありがとうのヒント – oScarDiAnno

+1

@oScarDiAnno単純なネストされた2つのfor-loops(各アイテムをすべての残りのアイテムと比較して最大値を更新する)で、より洗練されていないソリューションを探しているならば、私は答えを更新します – alfasin

+0

私はこれのような何かをしようとしていた!私はすでに持っている知識でそれを行う方法があることを知っていた、と私はちょっと同じ考えを持っていたが、それが正しく動作するように問題を抱えていた。私はあなたがしたことを見て、これは私に理解しやすいです。ありがとうございます:) – oScarDiAnno

関連する問題