RunnerLee

php 实现字典树

June 11, 2018 · · Updated June 15, 2018

又称单词查找树,Trie 树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 – 百度百科

放一下维基百科用的图

先堆一个我的实现, 目前还有一些问题是需要了解的:

  • 二元组, 三元组的区别
  • 压缩实现
  • 貌似与 KMP 算法可以结合提升效率
<?php
function make(array $words) {
    $nodes = [
        [false, []],    // 根节点
    ];

    $count = 1;

    foreach ($words as $word) {
        $current = 0;   // 重置至根节点

        for ($i = 0; $i < strlen($word); ++$i) {
            $alpha = $word{$i};
            if (isset($nodes[$current][1][$alpha])) {
                $current = $nodes[$current][1][$alpha];
                continue;
            }

            $nodes[$current][1][$alpha] = $count;
            $nodes[$count] = [false, []];
            $current = $count;
            ++$count;
        }

        $nodes[$current][0] = true;
    }

    return $nodes;
}

function search($needle, array $words)
{
    $nodes = make($words);

    $return = [];

    $current = 0;

    // 回溯位置, 相当于跟屁虫, 在未有匹配时, i 走到哪里, p 就跟到哪里.
    // 而当有匹配时, 停止跟屁虫, 标记为开始匹配的位置.
    // 当匹配结束有产生匹配结果时, 用于截取出字符串. 截取后, 把 p 设置为 i + 1, 以防止重复执行执行
    $p = 0;

    for ($i = 0; $i < strlen($needle); ++$i) {
        $alpha = $needle{$i};
        if (!isset($nodes[$current][1][$alpha])) {
            $current = 0;
            $i = $p;
            $p = $i + 1;
            continue;
        }

        $current = $nodes[$current][1][$alpha];

        if (true === $nodes[$current][0]) {
            $return[] = substr($needle, $p, $i - $p + 1);

            // 如果被标注为叶子节点, 但实际并非叶子节点, 则跳过回溯
            if (0 === count($nodes[$current][1])) {
                $p = $i + 1;
                $current = 0;
            }
        }
    }

    return $return;
}

$arr = search('I am runnerlee', ['runner', 'runnerlee']);

print_r($arr);

另外, 将使用 trie 树, 来做两个东西:

  • 关键词查找
  • 基于白名单的邮箱地址过滤器

参考

  • https://segmentfault.com/a/1190000008877595
  • http://dsqiu.iteye.com/blog/1705697
  • http://xiezhenye.com/2009/08/php-%E7%89%88%E7%AE%80%E5%8D%95-trie-%E6%A0%91.html








  • About
  • Search
  • Powered by Jekyll using the Trio theme