问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

想用php做一个搜索功能,不知道错在哪里,各位大侠们帮帮忙

发布网友 发布时间:2022-04-26 17:18

我来回答

3个回答

懂视网 时间:2022-04-28 15:35

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

企业微信截图_15922885713947.png

实现原理

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

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

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

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

什么是Trie树

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

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

它有3个基本性质:

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

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

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

假如我们有如下字符串

hello,hi,today,touch,weak

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

企业微信截图_15922885809834.png

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

代码实现

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

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

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

第一步:构建Trie树

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

$charArray = preg_split('/(?<!^)(?!$)/u', $str);

然后对每个字符串执行addWordToTrieTree方法,这个方法将一个词加入到Trie树中,这里用到了递归的方法

 public function buildTrieTree($strList) {
 $tree = [];
 foreach($strList as $str) {
  $charArray = preg_split('/(?<!^)(?!$)/u', $str); 
  $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('/(?<!^)(?!$)/u', $prefix);
 $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('/(?<!^)(?!$)/u', $prefix);
 $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;
 }
 /**
 * 将字符串的数组构建成Trie树
 *
 * @param [array] $strList
 * @return void
 */
 public function buildTrieTree($strList) {
 $tree = [];
 foreach($strList as $str) {
  $charArray = preg_split('/(?<!^)(?!$)/u', $str); 
  $tree = $this->addWordToTrieTree($charArray, $tree);
 }
 return $tree;
 }
 /**
 * 把一个词加入到Trie树中
 *
 * @param [type] $charArray
 * @param [type] $tree
 * @return void
 */
 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] => 春天里
)

热心网友 时间:2022-04-28 12:43

mysql_select_db($database_name,$conn);//打开数据库
mysql_query('set names gb2312');
$sql="SELECT * FROM `fls_users` order by reg_subtime desc LIMIT 0 , 30";
//echo "$sql";

$result=mysql_query($sql);//执行一条数据查询
//$row=mysql_fetch_row($result);//数据显示
while($row=mysql_fetch_array($result))
{
顺序调成这个样子.要不然mysql_query('set names gb2312');不起做用;
照着改

热心网友 时间:2022-04-28 14:01

报什么错?
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
广告机与智能电视的区别在哪里? 电脑无线连接盒子电脑怎么无线连接小米盒子 u盘内的文件被隐藏了怎么恢复?U盘数据恢复操作方法 看u盘隐藏文件怎么看 u盘文件隐藏了怎么办 如何把u盘隐藏文件夹显示出来 u盘隐藏文件怎么显示出来 U盘文件被隐藏怎么恢复?最后一招轻松找回 u盘中文件被隐藏怎么办-(u盘中文件被隐藏怎么办) 优盘隐藏文件夹怎么找出来 PHP技术 如何实现网站内高效搜索? PHP如何实现模糊搜索? 如何用PHP和ajax实现实时搜索功能 如何用php实现动态搜索功能,希望大神指点一下思路。 thinkphp 怎么在模板页面做一个搜索功能 关于php 站内搜索 的实现~~ php程序中的搜索功能 如何用PHP制作搜索引擎 当兵到底累不累啊? php要实现简单的查找功能,只要一个输入查找内容的编辑框并且要和查找... 怎么用php实现站内搜索功能 php怎么实现根据图片搜索图片功能 当兵新兵连累吗, 怎么在网页上用PHP做个搜索功能? 当兵是不是很累啊? php 如何实现文章内容搜索? 我想知道当兵的人在部队生活是不是很累… EXCEL文档中打入的文字如何全部显示 php如何实现下拉框选中搜索功能 PHP中怎么实现关键字搜索? phpcms里如何实现多功能搜索 酷我音乐的微信先享卡什么 PHP 怎样实现随便输入一个字都能搜索全数据库的内容? 我新办了微信先享卡,月费折扣是立即生效的吗? 微信先享卡不交钱会怎样? 微花先享后付怎么取消 有人知道微信先享卡吗? 微花的先享后付魅力那么大吗?为什么身边好多人都在用微花,不怕是套路贷嘛 酷我音乐微信先享卡首月付费不能付费是为什么? 有谁了解微花的那个先享后付模式吗?懂的来说下 小绿人先享月卡什么意思 目前微信先享卡怎么做的?商户想接入系统怎么接入呢? 哪个软件微信先用后付 月季花的颜色有多少种 月季花多少种颜色? 月季有几种颜色? 月季花都有什么颜色的 月季花有哪几种颜色? 月季花有多少种颜色的 月季花几种颜色?