字符串相关常见算法

文章介绍了使用Trie数据结构来解决字符串出现次数和公共前缀问题。TrieNode包含路径计数pass和结束标志end,以及26个子节点数组nexts。Trie类提供了插入、搜索和删除字符串的方法,通过ASCII码定位节点并更新计数。示例代码展示了如何插入一组字符串并进行操作。
摘要由CSDN通过智能技术生成

很久没有更新文档了
今天带一个leetcode常见的字符串算法,主要用于求字符串出现的次数和相同公共前缀
具体看下面的代码,最后会做出解释

class TrieNode {
   constructor() {
        this.pass = 0
        this.end = 0
        this.nexts = new Array(26)
    }
}


class Trie {
    constructor() {
        this.root = new TrieNode()
    }
    inset(word) {
        if (!word) {
            return
        }
        let node = this.root;
        node.pass++
        let index = 0
        for(let i = 0; i < word.length; i++) {
            index = word[i].charCodeAt() - 'a'.charCodeAt()
            if (!(node.nexts[index])) {
                node.nexts[index] = new TrieNode()
            }
            node = node.nexts[index]
            node.pass++
        }
        node.end++
    }
    // 查找字符串出现过几次
    search(word) {
        if (!word) {
            return 0;
        }
        let node = this.root;
        let index = 0
        for(let i = 0; i < word.length; i++) {
            index = word[i].charCodeAt() - 'a'.charCodeAt()
            if (!(node.nexts[index])) {
                return 0
            }
            node = node.nexts[index]
        }
        return node.end
    }
    // 查询字符串前缀出现了几次
    searchPer(word) {
        if (!word) {
            return 0
        }
        let node = this.root;
        let index = 0
        for(let i = 0; i < word.length; i++) {
            index = word[i].charCodeAt() - 'a'.charCodeAt()
            if (!(node.nexts[index])) {
                return 0
            }
            node = node.nexts[index]
        }
        return node.pass
    }
    // 删除节点
    delete(word) {
        // 判断节点有没有插入过
        if (this.search(word) === 0) {
            return 0;
        }

        let node = this.root;
        node.pass--
        let index = 0
        for(let i = 0; i < word.length; i++) {
            index = word[i].charCodeAt() - 'a'.charCodeAt()
            if (--(node.nexts[index].pass) == 0) {
                node.nexts[index] = null
                return;
            }
            node = node.nexts[index]
        }
        node.end--
    }
}



const trieNodes = new Trie()


let arrMapList = ["abc", "ab", "cd", "dc", "a"]

arrMapList.forEach(item => {
	trieNodes.inset(item)
})

TrieNode是数据结构类

  • pass表示节点的路径次数
  • end表示一个字符串结尾的次数
  • nexts下级节点(abc, ab, a) 头部都是a,那 abc, ab, a 都存储在一个nexts中

Trie 算法实现类

实例化类的时候就初始化数据结构
inset函数用于将所有字符串插入到nexts中
重点在这一块代码

index = word[i].charCodeAt() - 'a'.charCodeAt()
if (!(node.nexts[index])) {
	node.nexts[index] = new TrieNode()
}
node = node.nexts[index]
node.pass++
// 字符串都是a-z
// 那只要每一个字符串 Unicode码 - a的Unicode码,就能得出存储位置
// 判断!(node.nexts[index] 这个字母有没有没存储过,如果没有就构建
// node = node.nexts[index] 指针位移到下一个节点
// 节点pass++

直接把代码复制到编辑器里面,调试一边就懂了,很简单。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值