Hatena::Grouptopcoder

れんしゅうちょう。 このページをアンテナに追加 RSSフィード

 | 

2011-05-27[GCJ]復習かつ復讐

GCJ 2011のR1A-BのThe Killer Word。

Patrickの敵を取ったのを忘れていたので、一応書いておこうかとか。

Largeで140秒くらい。

class Word
    def initialize(w, i = nil)
        @to_s = w
        @id = i
        @length = w.length
        @mask = [0]*26
        for i in 0...26
            for j in 0...w.size
                @mask[i] <<= 1
                @mask[i] += 1 if w[j].ord == ('a'.ord + i)
            end
        end
    end
    attr_accessor :to_s, :id, :length
    def mask(c)
        @mask[c.ord - 'a'.ord]
    end
end
def searchKillerWord(dic, ls)
    res = dic[0]
    max = 0
    dp = dic.group_by{|w| w.length}.map{|len,ws| [0, ws]}
    ls.each do |ask|
        nextdp = []
        dp.each do |cnt, words|
            grp = words.group_by{|w| w.mask(ask)}
            grp.each do |pat, ws|
                ncnt = cnt
                ncnt += 1 if pat.zero? && grp.size != 1
                if ws.size != 1
                    nextdp << [ncnt, ws]
                elsif max < ncnt || (max == ncnt && res.id > ws[0].id)
                    max = ncnt
                    res = ws[0]
                end
            end
        end
        dp = nextdp
    end
    res
end
1.upto(gets.to_i) do |case_number|
    n,m=gets.split.map(&:to_i)
    result = []
    dic = []
    n.times do |i|
        w = Word.new(gets.chomp, i)
        dic << w
    end
    m.times do
        line = gets.chomp.split("")
        result << searchKillerWord(dic, line)
    end
    puts "Case ##{case_number}: #{result*" "}"
end

考え方は相変わらずで、再帰をやめてDPにしたのと、Wordとかいうクラス作って、マスクを最初に一回するだけにしたくらい。

クラス作ってる人が結構居て、おいしそうだと思ってパクってみたら、随分と見通しが良くなった。比較的綺麗に書けたと思う。

group_byなんていうのが備わっているあたり、やっぱりRubyぱない。

 |