Trie树 - 字符串多模式匹配

Trie 树的本质,就是利用字符串之间的公共前缀,将重复的前缀合并在一起

构建 Trie 树的过程比较耗时,对于有 n 个字符的字符串集合而言,需要遍历所有字符,对应的时间复杂度是 O(n),但是一旦构建之后,查询效率很高,如果匹配串的长度是 k,那只需要匹配 k 次即可,与原来的主串没有关系,所以对应的时间复杂度是 O(k),基本上是个常量级的数字。

应用场景:
1.敏感词过滤
2.搜索框联想

PHP

class TrieNode
{
    public $value;
    public $children = [];
    public $isEnd = false;

    public function __construct($value)
    {
        $this->value = $value;
    }
}

class Trie
{
    public $root;

    public function __construct()
    {
        $this->root = new TrieNode('/');
    }

    public function add($str)
    {
        $len = mb_strlen($str);
        $parent = $this->root;
        for ($i = 0; $i < $len; $i++) {
            if ($parent->children[$str[$i]] == null) {
                $parent->children[$str[$i]] = new TrieNode($str[$i]);
            }
            $parent = $parent->children[$str[$i]];
        }
        $parent->isEnd = true;
    }

    public function search($str)
    {
        $len = mb_strlen($str);
        $parent = $this->root;
        for ($i = 0; $i < $len; $i++) {
            if ($parent->children[$str[$i]]->value != $str[$i]) {
                return false;
            }
            $parent = $parent->children[$str[$i]];
        }
        return $parent->isEnd;
    }
}

$strArr = [
    'tom',
    'tomhaha',
    'tom2333',
    'jack'
];
$trie = new Trie;
foreach ($strArr as $str) {
    $trie->add($ str);
}
var_dump($trie->search('tom'));

GO

package main

import (
	"fmt"
)

type TreeNode struct {
	value string
	isEnd bool
	children map[rune]*TreeNode
}

func main() {
	strArr := []string{"tom", "tom2333", "tomhaha", "jack"}
	root := newTreeNode("/")
	for _, s := range strArr {
		root.add(s)
	}
	fmt.Println(root.search("tomhaha"))
}

func (node *TreeNode) add(str string) {
	current := node
	for _,s := range str {
		if current.children[s] == nil {
			current.children[s] = newTreeNode(string(s))
		}
		current = current.children[s]
	}
	current.isEnd = true
}

func (node *TreeNode) search(str string) bool {
	current := node
	for _,s := range str {
		if current.children[s].value != string(s) {
			return false
		}
		current = current.children[s]
	}
	return current.isEnd
}

func newTreeNode(value string) *TreeNode {
	return &TreeNode{
		value: value,
		isEnd: false,
		children: make(map[rune]*TreeNode),
	}
}

你可能感兴趣的:(算法与数据结构,字符串匹配,php,go,trie树)