业界动态
php 实现联想式 搜索,PHP实现搜索联想功能(基于字典树算法)
2024-12-30 05:29

搜索联想功能是各大搜索引擎具备的基础功能,如下图所示,这个功能简化了用户的输入行为,并且能够给用户推荐热门的搜索词,下面我们来讲一下如何用php实现搜索联想的功能。

实现原理

搜索联想功能拆解一下由两部分组成

1、给定一个查询词,找出以他为前缀的其他目标查询词

2、对目标查询词进行排序,选出权重高的若干个查询词

本篇中重点讲解一下第一部分的实现,这里使用Trie树,也叫字典树,这个数据结构来解决这个问题。通过Trie树可以很方便快速的找到已该字符串为前缀的目标字符串。

什么是Trie树

Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:最大限度地减少无谓的字符串比较,查询效率往往比哈希表高。

Trie的核心思想是空间换时间。利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的。

它有3个基本性质

1、根节点不包含字符,除根节点外每一个节点都只包含一个字符。

2、从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。

3、每个节点的所有子节点包含的字符都不相同。

假如我们有如下字符串hello,hi,today,touch,weak

那么构造出来的Trie树如下图所示

当查询的时候只需要从根开始按字符沿着树进行深度遍历,就可以把已该词为前缀的其他查询词查找出来。

代码实现

用于实现搜索联想功能的核心方法有两个

1、将查询词的数据集构建成Trie树

2、查找以某个查询词为前缀的所有查询词

第一步:构建Trie树

注意由于一个字符串有中文有英文,所以对每个字符串使用以下代码进行了分割,将字符串转化成了一个字符的数组$charArray = preg_split('/(?

然后对每个字符串执行addWordToTrieTree方法,这个方法将一个词加入到Trie树中,这里用到了递归的方法public function buildTrieTree($strList) {

$tree = [];

foreach($strList as $str) {

$charArray = preg_split('/(?

$tree = $this->addWordToTrieTree($charArray, $tree);

}

return $tree;

}

public function addWordToTrieTree($charArray, $tree) {

if (count($charArray) == 0) {

return [];

}

$char = $charArray[0];

$leftStr = array_slice($charArray, 1);

$tree[$char] = $this->addWordToTrieTree($leftStr, $tree[$char]);

return $tree;

}

第二步:查询前缀词

查询前缀词即给定一个字符串,查询树中所有以该串为前缀的字符串,也就是联想的过程。

首先调用findSubTree方法,从Trie中找到该前缀所在的子树,然后调用traverseTree方法,遍历这颗子树,把所有的字符串都提取出来,这里也是用了递归的方法。public function queryPrefix($prefix) {

$charArray = preg_split('/(?

$subTree = $this->findSubTree($charArray, $this->tree);

$words = $this->traverseTree($subTree);

foreach($words as &$word) {

$word = $prefix . $word;

}

return $words;

}

public function findSubTree($charArray, $tree) {

foreach($charArray as $char) {

if (in_array($char, array_keys($tree))) {

$tree = $tree[$char];

} else {

return [];

}

}

return $tree;

}

public function traverseTree($tree) {

$words = [];

foreach ($tree as $node => $subTree) {

if (empty($subTree)) {

$words[] = $node;

return $words;

}

$chars = $this->traverseTree($subTree);

foreach($chars as $char) {

$words[] = $node . $char;

}

}

return $words;

}

代码与测试结果

完整代码:<?php

class TrieTree {

private $tree;

public function __construct($strList) {

$this->tree = $this->buildTrieTree($strList);

}

public function queryPrefix($prefix) {

$charArray = preg_split('/(?

$subTree = $this->findSubTree($charArray, $this->tree);

$words = $this->traverseTree($subTree);

foreach($words as &$word) {

$word = $prefix . $word;

}

return $words;

}

public function findSubTree($charArray, $tree) {

foreach($charArray as $char) {

if (in_array($char, array_keys($tree))) {

$tree = $tree[$char];

} else {

return [];

}

}

return $tree;

}

public function traverseTree($tree) {

$words = [];

foreach ($tree as $node => $subTree) {

if (empty($subTree)) {

$words[] = $node;

return $words;

}

$chars = $this->traverseTree($subTree);

foreach($chars as $char) {

$words[] = $node . $char;

}

}

return $words;

}

public function buildTrieTree($strList) {

$tree = [];

foreach($strList as $str) {

$charArray = preg_split('/(?

$tree = $this->addWordToTrieTree($charArray, $tree);

}

return $tree;

}

public function addWordToTrieTree($charArray, $tree) {

if (count($charArray) == 0) {

return [];

}

$char = $charArray[0];

$leftStr = array_slice($charArray, 1);

$tree[$char] = $this->addWordToTrieTree($leftStr, $tree[$char]);

return $tree;

}

public function getTree() {

return $this->tree;

}

}

$strList = ['春风十里','春天在哪里','一百万个可能','一千年以后','后来','后来的我们','春天里','后会无期'];

$trieTree = new TrieTree($strList);

print_r($trieTree->getTree());

$prefix '春';

$queryRes = $trieTree->queryPrefix($prefix);

print_r($queryRes);

将’春风十里’,‘春天在哪里’,‘一百万个可能’,‘一千年以后’,‘后来’,‘后来的我们’,‘春天里’,'后会无期’这些歌名作为数据集,构建一个Trie树并进行测试。

可以看到输出以下结果

Trie树:Array

(

[春] => Array

(

[风] => Array

(

[十] => Array

(

[里] => Array

(

)

)

)

[天] => Array

(

[在] => Array

(

[哪] => Array

(

[里] => Array

(

)

)

)

[里] => Array

(

)

)

)

[一] => Array

(

[百] => Array

(

[万] => Array

(

[个] => Array

(

[可] => Array

(

[能] => Array

(

)

)

)

)

)

[千] => Array

(

[年] => Array

(

[以] => Array

(

[后] => Array

(

)

)

)

)

)

[后] => Array

(

[来] => Array

(

[的] => Array

(

[我] => Array

(

[们] => Array

(

)

)

)

)

[会] => Array

(

[无] => Array

(

[期] => Array

(

)

)

)

)

)

查询以“春为前缀的字符串”Array

(

[0] => 春风十里

[1] => 春天在哪里

[2] => 春天里

)

    以上就是本篇文章【php 实现联想式 搜索,PHP实现搜索联想功能(基于字典树算法)】的全部内容了,欢迎阅览 ! 文章地址:https://sicmodule.kub2b.com/news/13328.html
     栏目首页      相关文章      动态      同类文章      热门文章      网站地图      返回首页 企库往资讯移动站 https://sicmodule.kub2b.com/mobile/ , 查看更多   
最新文章
发改委:推进户用光伏发展,助力农民拓宽增收新路径
中国产品流通经纪人协会供销合作行业标准《农产品食品供应商信用评价规范》参编单位征集函中国农产品流通经纪人协会供销合作行业
泉州百度爱采购运营介绍
百度爱采购入驻条件有哪些:商家需持有工商行政管理局颁发的营业执照,并且执照在6个月有效期内;厂家商品真实在营且符合国家相
抖音feed是什么 feed广告投放流程
feed是什么?feed流(又称信息流)它是穿插在App内容中的广告,具有原生沉浸式体验,支持多种展现形式。feed可以进行线索收集,
抖音投流怎么投?找到最合适的优化路线,实现精准引流与高效转化!
在如今竞争激烈的市场中,抖音广告已经成为商家吸引流量、增加曝光和转化的重要工具。很多企业都在问:“抖音投流怎么投,才能真
提升脸书播放/浏览量:Facebook Workplace的策略
以下介绍:提升脸书播放/浏览量:Facebook Workplace的策略关于提升脸书播放/浏览量:Facebook Workplace的策略所提到的问题请大
想换07年左右的老车,值得吗?
百车全说别人研究车,而我研究你!问:想买一辆2007年左右,绿色(丨), 3.0。主要是喜欢这种雪茄车身,想留着自己偶尔开一下,家
年度盘点丨西安:2024年度十大交通精细化治理案例
​​2024年,西安公安交警深入践行以人民为中心的发展思想,聚焦群众反映强烈的交通问题,坚持缓堵保畅、全域治理,坚持小切口入
怎样才能很好的提高百度SEO的排名呢
怎样使自己的网站在百度等搜索引擎排名靠前  提高用户体验确保网站加载速度快,移动设备友好,并提供良好的用户互动体验。利用
《人工智能:未来世界的“智慧引擎”》
在当今这个科技飞速发展的时代,人工智能(Artificial Intelligence,简称AI)正以前所未有的速度重塑
未来直播技术的创新与发展方向
随着信息技术的快速发展和移动互联网的广泛普及,直播已经成为当今互联网领域的重要应用之一。从最初的娱乐直播到现在的教育直播