長さ 100 の文字列が与えられた場合
book bookstore bookworm booking book cooking boring bookingservice.... ok
0123456789... ... 100
アルゴリズムは次のようになります。
異なる開始点と部分文字列の長さから部分文字列を調査します。0 から始まり、長さが 1 ~ 100 のすべての部分文字列を取得します。つまり、0-1、0-2、0-3、... であり、これらの部分文字列のいずれかが文字列全体で複数回発生するかどうかを確認します。1 から始まるすべての部分文字列 (1-2、1-3、1-4... など) を 99-100 に達するまで検索しながら、位置を増やしながら文字列を進めていきます。
すべての部分文字列とその出現回数のテーブルを保持し、それらを並べ替えることができます。
最小長と最大長を指定することで最適化できます。これにより、検索数とヒット精度が大幅に減少します。さらに、部分文字列が見つかったら、検索された部分文字列の配列に保存します。部分文字列が再び見つかった場合は、スキップしてください。(つまり、book
すでにカウントしたヒットは、次の部分文字列をヒットしたときに再度カウントする必要はありませんbook
)。さらに、文字列全体の半分よりも長い文字列を検索する必要はありません。
文字列の例では、文字列の一意性について追加のテストを実行できます。あなたが持っているだろう
o x ..
oo x 7
bo x 7
ok x 6
book x 5
booking x 2
bookingservice x 1
3 より短い文字列 (およびテキスト文字列全体の半分より長い文字列) を無視すると、次のようになります。
book x 5
booking x 2
bookingservice x 1
これはすでにかなり妥当な結果です。
[編集] これは明らかに、自然な単語だけでなく、すべての文字列を調べます。
[編集] 通常、私は OP のコードを書くのが好きではありませんが、この場合は少し興味がありました:
$string = "book bookshelf booking foobar bar booking ";
$string .= "selfservice bookingservice cooking";
function search($string, $min = 4, $max = 16, $threshhold = 2) {
echo "<pre><br/>";
echo "searching <em>'$string'</em> for string occurances ";
echo "of length $min - $max: <br/>";
$hits = array();
$foundStrings = array();
// no string longer than half of the total string will be found twice
if ($max > strlen($string) / 2) {
$max = strlen($string);
}
// examin substrings:
// start from 0, 1, 2...
for ($start = 0; $start < $max; $start++) {
// and string length 1, 2, 3, ... $max
for ($length = $min; $length < strlen($string); $length++) {
// get the substring in question,
// but search for natural words (trim)
$substring = trim(substr($string, $start, $length));
// if substring was not counted yet,
// add the found count to the hits
if (!in_array($substring, $foundStrings)) {
preg_match_all("/$substring/i", $string, $matches);
$hits[$substring] = count($matches[0]);
}
}
}
// sort the hits array desc by number of hits
arsort($hits);
// remove substring hits with hits less that threshhold
foreach ($hits as $substring => $count) {
if ($count < $threshhold) {
unset($hits[$substring]);
}
}
print_r($hits);
}
search($string);
?>
コメントと変数名は、コード自体を説明するものでなければなりません。あなたの場合、 $string はファイルの読み取りに使用されます。この例では、次のように出力されます。
searching 'book bookshelf booking foobar bar booking selfservice
bookingservice cooking' for string occurances of length 4 - 16:
Array
(
[ook] => 6
[book] => 5
[boo] => 5
[bookin] => 3
[booking] => 3
[booki] => 3
[elf] => 2
)
実装方法を教えてください:)