2010-01-28 63 views
6

鑑於我有3個字符串數組:查找常見字符串中的字符串(紅寶石)的陣列

["Extra tv in bedroom", 
"Extra tv in living room", 
"Extra tv outside the shop"] 

如何找到最長的字符串的所有字符串有什麼共同點?

+0

你的意思是'任何'子串,還是隻應該從頭開始比較? – 2010-01-28 22:14:27

+0

也問這裏:http://rosettacode.org/wiki/Longest_Common_Subsequence – 2010-01-29 00:21:41

+0

@ St.Woland:實際上,這取決於。對於我的特定例子,結果將是相同的。但我要問的原因實際上是因爲我想知道如何爲任何給定的字符串排列找到一個「公分母」的表單。 – 2010-01-29 13:16:03

回答

11

這裏做的rubyish方式它。您應該使用更先進的算法,如果你有一大堆的字符串或者他們是很長,但:

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"]) 
2

This wikipedia article解釋了可用於解決該問題的兩種算法。

+1

這篇wiki文章給出了兩個字符串的完整解決方案:http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Longest_common_substring#Ruby – 2010-01-28 22:15:29

2

如果你要搜索的所有字符串的開頭:

來源

def substr(a) 
    return "" unless (a.length > 0) 
    result = 0 
    (0 ... a.first.length).each do |k| 
     all_matched = true 
     character = a.first[k] 
     a.each{ |str| all_matched &= (character == str[k]) } 
     break unless all_matched 
     result+=1 
    end 
    a.first.slice(0,result) 
end 

測試

input = ["Extra tv in bedroom", 
"Extra tv in living room", 
"Extra tv outside the shop"] 

puts substr(input) + "." 

輸出

Extra tv . 
0

不要以爲這擴展特別好。

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"]) 
1

也只適用於字符串的開頭。

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

不知道響應是否仍然有用,但這裏有一個解決方案,它受@mckeed和@ lins314159代碼的啓發。

def longest_common_substr(strings) 
    longest_substring = strings.map{|s| s.split}.max_by &:length 
    longest_substring.inject do |target_str, token| 
     r = Regexp.new("^#{target_str.nil? ? token : "#{target_str} #{token}".strip}") 
     target_str = "#{target_str} #{token}".strip if strings.all? {|string| string =~ r} 
     target_str 
    end 
end 

puts longest_common_substr(["Extra tv and mat in bedroom", 
          "Extra tv and chair with view in living room", 
          "Extra tv and carpet outside the shop"])