文字列マッチング
概要
文字列マッチングは、テキストデータに含まれる特定の部分文字列 (パターン) を効率的に検索する技術である。大きな文書や巨大なデータベースで特定の単語やフレーズを見つけ出すために使用される。
Table of Contents
文字列マッチングの課題は次のように定義される。
入力: テキスト
とパターン (検索文字列) 。 出力: パターン
がテキスト の中に現われる最初の位置、またはすべての位置。
たとえば
Naïve アルゴリズム
ナイーブアルゴリズムによる文字列マッチングはテキスト
function naive(text, pattern) {
let results = [];
for (let i=0; i <= text.length-pattern.length; i++) {
let j;
for (j=0; j < pattern.length; j++) {
if (text[i+j] !== pattern[j]) {
break;
}
}
if (j === pattern.length) {
results.push(i);
}
}
return results;
}
Rabin-Karp アルゴリズム
Rabin-Karp はテキスト
ローリングハッシュ
ローリングハッシュ (rolling hash) は文字列のスライディングウィンドウに対して効率的にハッシュ値を更新できるハッシュ法である。Rabin-Karp アルゴリズムではローリングハッシュを使用して計算量を削減している。
ローリングハッシュの基本的なアイディアは、文字列
ローリングハッシュの単純な例は、
Rabin-Karp 文字列マッチング
Rabin-Karp アルゴリズムで使用されるローリングハッシュは Rabin フィンガープリント (Rabin fingerprint) に基づいている。これは式 (
式 (
このようなローリングハッシュ関数
| 1. | |
|
| 2. | |
|
| 3. | |
|
| 4. | |
|
| 5. | |
|
| 6. | |
|
| 7. | |
|
| 8. | |
|
8 行目のローリングハッシュ
function rabinKarp(text, pattern) {
const base = 256; // 基数(ASCII文字の場合は256が一般的)
const mod = 101; // モジュロ(素数)
let patternHash = 0;
let currentHash = 0;
let highestBase = 1;
let result = [];
// パターンと最初のテキスト部分文字列のハッシュ値を計算
for(let i=0; i < pattern.length; i++) {
patternHash = (patternHash * base + pattern.charCodeAt(i)) % mod;
currentHash = (currentHash * base + text.charCodeAt(i)) % mod;
if(i < pattern.length - 1) {
highestBase = (highestBase * base) % mod;
}
}
// テキスト内の部分文字列をスライドしてハッシュ値を比較
for(let i=0; i <= text.length - pattern.length; i++) {
if(currentHash === patternHash) {
// ハッシュ値が一致する場合、文字ごとの比較を行う
if(text.substr(i, pattern.length) === pattern) {
result.push(i);
}
}
// 次の部分文字列のハッシュ値を計算
if(i < text.length - pattern.length) {
currentHash = ((currentHash - text.charCodeAt(i) * highestBase) * base + text.charCodeAt(i + pattern.length)) % mod;
if(currentHash < 0) {
currentHash += mod;
}
}
}
return result;
}
ただし、最悪ケースでの計算量が多いことから、Rabin-Karp アルゴリズムは Knuth-Morris-Pratt や Boyer-Moore、その他のより高速な文字列マッチングよりも劣っている [1]。
Boyer-Moore アルゴリズム
Boyer-Moore アルゴリズムは最も効率的な文字列マッチングアルゴリズムであると考えられており、通常の文字列マッチングアプリケーションでは Knuth-Morris-Pratt アルゴリズムに比べても大幅に優れている [1]。このアルゴリズムやその簡略版はしばしばテキストエディタの検索や置換として実装されている。
参考文献
- Himanshu B. Dave. Design and Analysis of Algorithms. ピアソン (2013)