8
votes

Trouver une chaîne commune dans une matrice de chaînes (Ruby)

Donné, j'ai un tableau de 3 chaînes: xxx

Comment puis-je trouver la chaîne la plus longue que toutes les cordes ont en commun?


4 commentaires

Voulez-vous dire «tout» sous-chaîne ou ne doit-il être comparé que depuis le début?


A également demandé ici: ROSETACODE.ORG/WIKI/LGONGEST_COMMON_SUTINCE


@ St.Woland: En fait, cela dépend. Pour mon exemple particulier, le résultat serait le même. Mais la raison pour laquelle je me demande était en fait parce que je voulais savoir ce que je pouvais faire pour localiser un formulaire pour "dénominateur commun" pour tout étant donné de chaînes.


@glenn: la plus longue recherche courante est différente car elle n'a pas à être contiguës.


7 Réponses :


2
votes

Cet article Wikipedia explique deux algorithmes pouvant être utilisés pour résoudre ce problème.


1 commentaires

Et cet article Wiki donne une solution complète pour deux chaînes: en.wikibooks.org/ wiki / algorithme_implementation / cordes / ...



3
votes

Si vous souhaitez rechercher le début de toutes les chaînes:

source xxx

test xxx

Sortie xxx


0 commentaires

19
votes

Voici une façon rubish de le faire. Vous devez utiliser un algorithme plus avancé si vous avez un groupe de cordes ou qu'ils sont très longs, bien que:

def longest_common_substr(strings)
  shortest = strings.min_by &:length
  maxlen = shortest.length
  maxlen.downto(0) do |len|
    0.upto(maxlen - len) do |start|
      substr = shortest[start,len]
      return substr if strings.all?{|str| str.include? substr }
    end
  end
end

puts longest_common_substr(["Extra tv in bedroom",
                            "Extra tv in living room",
                            "Extra tv outside the shop"])


0 commentaires

0
votes

Ne pensez pas que cette échelle est particulièrement bien.

def longest_substr(text)
    if (text.length == 0)
        return ""
    elseIf (text.length == 1)
        return text[0]
    end
    longest = text.inject(text[0].length) {|min, s| min < s.length ? min : s.length}
    (1 .. longest).to_a.reverse.each do |l|
        (0 .. text[0].length - l).each do |offset|
            str = text[0].slice(offset, l)
            matched = (1 .. text.length - 1).inject(true) {|matched, i| matched && text[i].index(str) != nil}
            if (matched)
                return str
            end
        end
    end

    return ""
end

puts longest_substr(["Alice's Extra tv in bedroom",
    "Bob's Extra tv in living room",
    "My Extra tv outside the shop"])


0 commentaires

1
votes

Aussi uniquement pour le début des chaînes.

def longest_subsequence array
  array.sort!
  first = array[0].split(//)
  last = array[-1].split(//)
  length = (first.size > last.size) ? last.size : first.size
  sequence = ""
  index = 0
  while (first[index] == last[index]) && (index < length)
    sequence << first[index]
    index += 1
  end
  sequence
end


0 commentaires

0
votes

Je ne sais pas si une réponse est toujours utile, mais voici une solution inspirée du code @mckeed et @ lins314159. XXX


0 commentaires

0
votes

Un meilleur formulaire:

  def longest_common_substring(strings)
    shortest = strings.min_by(&:size)
    max = shortest.size
    max.downto(0) do |size|
      0.upto(max - size) do |start|
        substring = shortest[start, size]
        return substring if strings.all? { |string| string.include? substring }
      end
    end
  end


0 commentaires