Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
全文検索のアルゴリズムとデータ構造
Search
toyama
December 13, 2020
330
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
全文検索のアルゴリズムとデータ構造
toyama
December 13, 2020
More Decks by toyama
See All by toyama
Path Copying による永続データ構造
toyama1710
0
720
Featured
See All Featured
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
320
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.7k
Building an army of robots
kneath
307
46k
Heart Work Chapter 1 - Part 1
lfama
PRO
10
36k
The Cost Of JavaScript in 2023
addyosmani
55
10k
Making Projects Easy
brettharned
120
6.8k
The Invisible Side of Design
smashingmag
301
52k
Build your cross-platform service in a week with App Engine
jlugia
234
19k
Deep Space Network (abreviated)
tonyrice
0
310
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
570
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
410
Transcript
Hugo でブログ作成 会津大学 学部1年 toyama1710
自己紹介 • HN: 遠山 • Twitter: @toyama_pts • github: toyama1710
• 趣味: 絵, バイク
はじめに • ブログを作りました ◦ https://blog.toyama1710.net • 見てね!
Hugo • SSG の一種 • markdown で書いた記事を html に変換してくれる
記事検索機能 • タグ検索 • カテゴリ検索
記事検索機能 • タグ検索 • カテゴリ検索 全文検索も欲しくないスカ?
文字列検索アルゴリズム Hugo でブログ作成 会津大学 学部1年 toyama1710 勉強したので知見共有するぜ!
問題設定
パターンマッチング 文字列 T は部分文字列として文字列 P を含むか? を判定する問題
パターンマッチング 例 • “アメリカンジョーク” に “カンジョー” は含まれる?
パターンマッチング 例 • “アメリカンジョーク” に “カンジョー” は含まれる? ◦ Yes
パターンマッチング 例 • “アメリカンジョーク” に “カンジョー” は含まれる? ◦ Yes •
“任意コードジッコウ” に “ドジッコ” は含まれる?
パターンマッチング 例 • “アメリカンジョーク” に “カンジョー” は含まれる? ◦ Yes •
“任意コードジッコウ” に “ドジッコ” は含まれる? ◦ Yes
パターンマッチング 例 • “アメリカンジョーク” に “カンジョー” は含まれる? ◦ Yes •
“任意コードジッコウ” に “ドジッコ” は含まれる? ◦ Yes • “Linux” に “Linx” は含まれる?
パターンマッチング 例 • “アメリカンジョーク” に “カンジョー” は含まれる? ◦ Yes •
“任意コードジッコウ” に “ドジッコ” は含まれる? ◦ Yes • “Linux” に “Linx” は含まれる? ◦ No
記法,用語の導入 • 文字列 T の長さを |T| と書く ◦ T =
“abc” のとき |T| = 3 ◦ S = “efghi” のとき |S| = 5
記法,用語の導入 • prefix ◦ 文字列の先頭部分を抜き出してきた文字列 ◦ “ABC” の prefix -
“ABC”, “AB”, “A”, “” • suffix ◦ 文字列の末尾部分を抜き出した文字列 ◦ “ABC” の suffix - “ABC”, “BC”, “C”, “”
注意 • 今回の LT では定数アルファベットを仮定 ◦ 文字の種類数は定数
総当たり
総当たり • T と P を一字ずつずらして一致比較 • 途中で異なる文字があれば T をずらしてもう一度
A I Z U U N I V U N I V P: T:
総当たり • T と P を一字ずつずらして一致比較 • 途中で異なる文字があれば T をずらしてもう一度
A I Z U U N I V U N I V P: T:
総当たり • T と P を一字ずつずらして一致比較 • 途中で異なる文字があれば T をずらしてもう一度
A I Z U U N I V U N I V P: T:
総当たり • T と P を一字ずつずらして一致比較 • 途中で異なる文字があれば T をずらしてもう一度
A I Z U U N I V U N I V P: T:
総当たり • T と P を一字ずつずらして一致比較 • 途中で異なる文字があれば T をずらしてもう一度
A I Z U U N I V U N I V P: T:
総当たり • T と P を一字ずつずらして一致比較 • 途中で異なる文字があれば T をずらしてもう一度
• 時間計算量: O(|T||P|) A I Z U U N I V U N I V P: T:
総当たり 1. 狂った僕が あああああああああああ....(100万字) とだけ書かれた記事を投稿
総当たり 1. 狂った僕が あああああああああああ....(100万字) とだけ書かれた記事を投稿 2. ユーザも狂って検索窓に ああああああああ....(100万+1字)
総当たり 1. 狂った僕が あああああああああああ....(100万字) とだけ書かれた記事を投稿 2. ユーザも狂って検索窓に ああああああああ....(100万+1字) 3. 検索が終わらない
ラビンカープ法
ラビンカープ法 • 基本方針 ◦ 文字列の比較をハッシュで行う ◦ O(|P|) -> O(1) へ改善!!
◦ 全体として O(|T| + |P|)
Rolling Hash
Rolling Hash - ラビンカープ法 • 部分文字列のハッシュを高速に計算できる • 文字列を B 進数として解釈して
MOD をとるだけ ◦ B > 1 の正整数 ◦ 素数で MOD を取ると一様分布しやすい
Rolling Hash - ラビンカープ法 • 文字列 S のハッシュ値が既に計算済み ◦ S
の末尾に 1 文字付け加える: O(1) ◦ S の先頭を 1 文字削除: O(1) • 検索位置をスライドしながらハッシュ値を計算可能 A I Z U U N I V U N I V P: T:
Rolling Hash - ラビンカープ法 • 文字列 S のハッシュ値 h ◦
S.push(c): h * B + c ◦ S.erase(0): h - S[0] * B^|P| A I Z U U N I V U N I V P: T:
Rolling Hash - ラビンカープ法 • 文字列 S のハッシュ値 h ◦
S.push(c): h * B + c ◦ S.erase(0): h - S[0] * B^|P| A I Z U U N I V U N I V P: T:
Rolling Hash - ラビンカープ法 • 文字列 S のハッシュ値 h ◦
S.push(c): h * B + c ◦ S.erase(0): h - S[0] * B^|P| • 検索位置のスライドが O(1) A I Z U U N I V U N I V P: T:
Rolling Hash - ラビンカープ法 • 文字列 S のハッシュ値 h ◦
S.push(c): h * B + c ◦ S.erase(0): h - S[0] * B^|P| • 検索位置のスライドが O(1) • O(|T| + |P|) A I Z U U N I V U N I V P: T:
Rolling Hash - ラビンカープ法 • 記事全体の文字数は 1万字を超える • ユーザが検索する語は 30
字も無いはず • まだ改善できそう
Suffix Trie お気に入りデータ構造
Suffix Trie の前に Trie について お気に入りデータ構造
Trie • こんな感じの木構造 • 根から頂点へのパスが単語を表す • apple • apart •
bug • bag a p p l e a r t b u g a g
Trie • 共通した prefix を持った単語の列挙が得意 • 根からラベルを辿っていくだけで OK • prefix:
ap • prefix: bu a p p l e a r t b u g a g
Suffix Trie 再び
Suffix Trie • Thm. ◦ 部分文字列は suffix の prefix
Suffix Trie • Thm. ◦ 部分文字列は suffix の prefix A
I Z U U N I V T: U U N I V U U
Suffix Trie • T の suffix を全部 Trie に入れちゃお!w •
マジでこれだけ T = “ababc” a b a b c c b a b c c c
Suffix Trie • T の suffix を全部 Trie に入れちゃお!w •
マジでこれだけ • 構築時間: O(|T|^2) • 空間計算量: O(|T|^2) • 検索時間: クエリ毎 O(|P|)
Suffix Trie • 流石にメモリを食いすぎ • 1万字で 1 GB 食う計算
DAWG - Directed Acyclic Word Graph Suffix Automaton の名でも親しまれる
DAWG • Suffix Trie をよく見ると全く同じ部分木がたくさん • 一つにまとめてしまおう T = “ababc”
a b a b c c b a b c c c
DAWG • 検索は Suffix Trie と同様始点から辺を辿っていく a b a b
c c b a b c c c
DAWG • 構築時間: O(|T|) • 空間計算量: O(|T|) • 検索時間: クエリ毎
O(|P|) • 満足しました
実測 - DAWG
実測 • AOJ ALDS1 - 14 D を解いてみます ◦ https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/14/
ALDS1_14_D • 冒頭の問題設定と全く同じ
実測 • AOJ ALDS1 - 14 D を解いてみます ◦ https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/14/
ALDS1_14_D • 冒頭の問題設定と全く同じ • |T| < 1,000,000 • |P| < 1,000 • クエリ数 10,000
実測 • はやい • はやいと、うれしい!!
参考文献 • 秋葉拓哉, 岩田陽一, 北川宣稔 プログラミングコンテストチャレンジ ブック[第二版] - マイナビ出版 •
Anselm Blumer, Janet Blumer, David Haussler, Andrzej Ehrenfeucht, M. T. Chen, and Joel I. Seiferas. The smallest automation recognizing the subwords of a text. Theoretical Computer Science, 40:31–55, 1985.
ありがとうございました 楽しんでいただけたなら幸いです