マナビング基本情報技術者

ハッシュ表の衝突はASCIIコードの差で見抜ける

基本情報技術者試験 令和6年度 問2 / アルゴリズムとプログラミング › アルゴリズム

過去問にチャレンジ

令和6年度 問2

キーが小文字のアルファベット1文字(a,b,…,z のいずれか)であるデータを,大きさが10のハッシュ表に格納する。ハッシュ関数として,アルファベットのASCIIコードを10進表記法で表したときの1の位の数を用いることにする。衝突が起こるキーの組合せはどれか。ASCIIコードでは,昇順に連続した2進数が,アルファベット順にコードとして割り当てられている。

  1. ア

    a と i

  2. イ

    b と r

  3. ウ

    c と l

  4. エ

    d と x

会話形式の解説

講師講師
今回はハッシュ表の衝突の問題です。衝突とは、異なるキーのハッシュ値が同じになって、同じ格納位置を指してしまうことです。注目点は、問題文の「アルファベット順に連続したコードが割り当てられている」という一文です。
受験者受験者
ASCIIコードの値を全部覚えていないと解けないのかと思って、手が止まりました。aが何番なのかも自信がありません。
講師講師
具体的な値を知らなくても解けます。コードが1ずつ連続しているので、2文字のコードの差は、アルファベット上の順番の差と同じになります。では、2つの数の1の位が一致するのは、差がどうなっているときでしょうか。
受験者受験者
たとえば13と23や、7と27のように、差が10や20のときですか。つまり差が10の倍数なら1の位がそろう、ということでしょうか。
講師講師
そのとおりです。1の位を取り出すのは、10で割った余りを求めるのと同じ操作なので、差が10の倍数なら余りが一致します。では、aとiの組から順番の差を数えてみましょう。
受験者受験者
aが1番目、iが9番目なので差は8です。10の倍数ではないので衝突しません。bとrは、bが2番目、rが18番目で差は16なので、これも違います。
講師講師
正確です。実際のコードでも確かめておくと、小文字はaが97から始まります。aは97でハッシュ値7、iは105でハッシュ値5です。bは98で8、rは114で4なので、どちらの組も別の位置に入ります。
受験者受験者
cとlは、cが3番目、lが12番目で差は9です。10にかなり近いので、最初は衝突しそうに感じました。
講師講師
そこが引っかけになりやすいところです。差が9では1の位はそろいません。cは99でハッシュ値9、lは108でハッシュ値8なので、1つずれます。「ほぼ10」ではなく「ちょうど10の倍数」かどうかを見るのが大切です。
受験者受験者
残りのdとxは、dが4番目、xが24番目で差は20です。10の倍数なので、この組が衝突するのですね。
講師講師
はい。実際のコードでもdは100、xは120で、ハッシュ値はどちらも0になります。異なるキーが同じ位置に格納されることになるので、dとxの組で衝突が起こります。
受験者受験者
計算が苦手でも、順番の差を数えて10の倍数かを見るだけなら短時間で判定できそうです。
講師講師
補足すると、一般に表の大きさがmで「mで割った余り」をハッシュ値にすると、差がmの倍数になるキー同士が衝突します。衝突は「シノニムの発生」とも呼ばれます。また、この問題ではハッシュ値が0〜9の10通りしかないので、26文字すべてを格納すれば必ずどこかで衝突が起こります。

まとめ

ASCIIコードを10進表記したときの1の位をハッシュ値にする場合、2つのキーが衝突するのはコードの差が10の倍数のときです。小文字のアルファベットはaの97から1ずつ連続してコードが割り当てられているので、コードの差はアルファベットの順番の差と同じになります。順番の差はaとiが8、bとrが16、cとlが9、dとxが20で、10の倍数になるのはdとxだけです。実際のコードでもdは100、xは120で、ハッシュ値はどちらも0になります。差が9の組は10に近いため間違えやすいですが、差がちょうど10の倍数かどうかを確かめれば判定できます。

解答・解説

正解はエです

この問題のテーマ

ASCIIコードの10進表記の1の位をハッシュ値にしたとき、どの2文字が同じ格納位置になる(衝突する)かを問う問題です。ハッシュ関数の性質と、文字コードが連続して割り当てられていることを組み合わせて考えます。

解き方の考え方

問題文にあるとおり、小文字はアルファベット順に連続したコードが割り当てられているので、2文字のコードの差はアルファベット上の順番の差と同じになります。1の位が一致するのは、コードの差が10の倍数のときです。そのため、ASCIIコードの具体的な値を覚えていなくても、各組の順番の差を数えれば判定できます。念のため、aを97とした実際のコードでも1の位を確かめます。

選択肢ごとの解説

  1. ×ア  a と i
    aとiの組は、aが1番目、iが9番目なのでコードの差は8です。10の倍数ではないため、1の位は一致しません。実際のコードでは、aが97でハッシュ値は7、iが105でハッシュ値は5となり、別の位置に格納されます。
  2. ×イ  b と r
    bとrの組は、bが2番目、rが18番目なのでコードの差は16です。10の倍数ではありません。実際のコードでは、bが98でハッシュ値は8、rが114でハッシュ値は4となり、衝突しません。
  3. ×ウ  c と l
    cとlの組は、cが3番目、lが12番目なのでコードの差は9です。差が10に近いため一致しそうに見えますが、10の倍数ではありません。実際のコードでは、cが99でハッシュ値は9、lが108でハッシュ値は8となり、衝突しません。
  4. ○エ  d と x
    dとxの組は、dが4番目、xが24番目なのでコードの差は20で、10の倍数です。実際のコードでも、dは100、xは120で、ハッシュ値はどちらも0になります。異なるキーが同じ位置に格納されることになるので、この組で衝突が起こります。

補足

一般に、表の大きさがmのときに「mで割った余り」をハッシュ値にすると、差がmの倍数になるキー同士が衝突します。この問題ではハッシュ値が0〜9の10通りしかないので、26文字すべてを格納すれば必ず衝突が起こります。ウのcとlのように差が9の組は「ほぼ10」なので間違えやすいですが、差がちょうど10の倍数になっているかを確かめれば判定できます。

POINT

  • 異なるキーのハッシュ値が同じになり、同じ格納位置を指すことを衝突(シノニムの発生)といいます。
  • 10進表記の1の位を取り出す操作は、10で割った余りを求める操作と同じです。
  • 2つの値の1の位が一致するのは、その差が10の倍数のときです。
  • 小文字アルファベットのASCIIコードは、aの97から順に1ずつ増えます。

※出典:令和6年度 基本情報技術者試験 科目A 問2