先頭から順番に1つずつ調べていき、文字列パターンが一致するまで進めていく。単純だけれど、効率はあまりよくない。
def simpleSearch( text, pattern )
n = 0
while n < text.length
much = false
# 検索状態を確認するための表示
printf " 本文 : #{text}¥nパターン : "
i = 0
while i < n
print(" ")
i += 1
end
puts "#{pattern}"
# 検索
i = 0
while i < pattern.length
if pattern[i] != text[n + i]
# 一致しなかったので、最初のループに戻る
much = false
break
end
much = true
i += 1
end
n += 1
return n if much == true
end
# 最終的に一致しなかった
return false
end
p simpleSearch("TeamSwift", "if")
p simpleSearch("TeamSwift", "id")
比較に失敗したときに、再比較を開始する位置を把握しておく。
理論上は非常に効率がいいが、現実的にはアルゴリズムが複雑な分、オーバヘッドが大きくなってしまい、あまり長くない文字列を検索する場合は、単純な文字列検索の方が良好なパフォーマンスを示すことが多い。
def kmpSearch( text, pattern )
textIndex = 1
patternIndex = 0
cacheTable = Array.new(pattern.length + 1)
cacheTable[0] = cacheTable[1] = 0
# KMP 検索に必要な情報を予め計算し、配列にキャッシュする
while pattern.length > textIndex
if pattern[textIndex] == pattern[patternIndex]
# 一致したら再比較は pattern_index 文字から始める
textIndex += 1
patternIndex += 1
cacheTable[textIndex] = patternIndex
elsif
# パターン1文字目で不一致なら再検索は先頭から
textIndex += 1
cacheTable[textIndex] = 0
else
# パターン1文字目以外で不一致なら再検索の位置は cache_table から参照
patternIndex = cacheTable[patternIndex]
end
end
# ここから実際の検索
i = 0
n = 0
while n < text.length
printf " 本文:#{text}¥n"
printf "パターン:"
l = 0
while l < n
printf " "
l += 1
end
printf "#{pattern[i].chr}¥n"
if text[n] == pattern[i]
# テキストとパターンが一致していれば、1字ずつ比較を続ける
n += 1
i += 1
if pattern.length == i
# 全て一致すれば OK
return n - pattern.length
end
elsif i == 0
# パターン最初の文字で失敗した場合は、比較場所を1つ進める
n += 1
else
# 最初の文字でない場合は、テーブルから比較位置を取得する
i = cacheTable[i]
end
end
return false
end
p kmpSearch("a eighty-eighty-eighth key", "eighty-eighth")
KMP 法では、文字列をパターンの前方から後方に向かって比較していたのに対して、BM法では、後方から前方に向かって比較する。
def bmSearch( text, pattern )
# 文字列で不一致が生じたときの比較点の移動量を予め計算してキャッシュするテーブル
cacheTable = Array.new(256)
# 不一致が生じた移動量を予め計算し、キャッシュする
cacheTable.each_index do |i|
cacheTable[i] = pattern.length
end
i = 0
while i < pattern.length
# パターンに含まれている文字は、それに併せてずらす。
# 同じ文字が複数含まれている場合は、最後に登場する文字にあわせる
cacheTable[pattern[i]] = pattern.length - i - 1
i += 1
end
# 移動量のキャッシュはここまで
textIndex = pattern.length - 1
while textIndex < text.length
printf " 本文:#{text}¥n"
printf "パターン:"
i = 0
while i < textIndex - pattern.length + 1
printf " "
i += 1
end
puts pattern
# パターンの後ろから比較を始める
patternIndex = pattern.length - 1
while text[textIndex] == pattern[patternIndex]
if patternIndex == 0
# パターンの先頭文字まで全て比較成功すれば OK
return textIndex
end
textIndex -= 1
patternIndex -= 1
end
if cacheTable[text[textIndex]] > pattern.length - patternIndex
# その文字に応じて比較点を移動
textIndex += cacheTable[text[textIndex]]
else
textIndex += pattern.length - patternIndex
end
end
return false
end
p bmSearch("On a dark desert highway, cool wind in my hair", "wind")