前缀树

Trie树 = 前缀树 = 字典树

使用场景:给两个数组,A = {"abc","bce","abd","bef"}, B = {"be","abc"}问:
1.B中哪些字符串是在A中出现的
2.A中哪些字符串是,以B中某个字符串为前缀的
3.问以"e"结尾的字符串有哪些?
思路:对A中所有字符串建立前缀树: "O"代表节点,"/"和"\"代表边,字符存在边上,

O                  每个节点还存着边上字符添加的次数以及以该节点边上字符结束的次数

a /       \ b            所以节点的数据结构如下,nodes表示当前节点指向的下一节点

O         O             Node {int path;int end; Node[] nodes}

b /           /c   \ e

O          O    O

c /  d\       /e    /f

O     O   O     O

public class Code_01_TrieTree {


public static class TrieNode {

public int path;

public int end;

public TrieNode[] nexts;


public TrieNode() {

path = 0;

end = 0;

nexts = new TrieNode[26]; // 字母有26位

}

}


public static class Trie {

private TrieNode root;


public Trie() {

root = new TrieNode();

}


public void insert(String word) {

if (word == null) {

return;

}

char[] chs = word.toCharArray();

TrieNode node = root;

int index = 0;

for (int i = 0; i < chs.length; i++) { // 遍历每一个字符

index = chs[i] - 'a'; // 字符与'a'的距离表示下一节点的边上存着的字符

if (node.nexts[index] == null) {

node.nexts[index] = new TrieNode();

}

node = node.nexts[index]; // 节点一直向下走

node.path++;

}

node.end++; // 节点停留在最后一个字符,以该节点结尾的次数+1

}


public void delete(String word) {

if (search(word) != 0) {

char[] chs = word.toCharArray();

TrieNode node = root;

int index = 0;

for (int i = 0; i < chs.length; i++) {

index = chs[i] - 'a';

if (--node.nexts[index].path == 0) { // 找到匹配的字符,如果该字符只出现过一次,该字符所在的节点的上一节点直接指向null,无需匹配后面的

node.nexts[index] = null;

return;

}

node = node.nexts[index];

}

node.end--;

}

}


public int search(String word) { // 有没有相同的字符串,字符串word在前缀树中出现了几次,

if (word == null) {

return 0;

}

char[] chs = word.toCharArray();

TrieNode node = root;

int index = 0;

for (int i = 0; i < chs.length; i++) {

index = chs[i] - 'a';

if (node.nexts[index] == null) {

return 0;

}

node = node.nexts[index];

}

return node.end; // 跟插入差不多,找到最后一个字符的节点,返回节点上以该字符串结尾的次数

}


public int prefixNumber(String pre) { // 以pre为前缀

if (pre == null) {

return 0;

}

char[] chs = pre.toCharArray();

TrieNode node = root;

int index = 0;

for (int i = 0; i < chs.length; i++) {

index = chs[i] - 'a';

if (node.nexts[index] == null) {

return 0;

}

node = node.nexts[index];

}

return node.path;

}

}

public static void main(String[] args) {


Trie trie = new Trie();

System.out.println(trie.search("jin"));

trie.insert("jin");

System.out.println(trie.search("jin"));

trie.delete("jin");

System.out.println(trie.search("jin"));

trie.insert("jina");

trie.insert("jinb");

System.out.println(trie.prefixNums("jin"));

}
}

全部评论

相关推荐

Kurumis:整个简历看下来就发现你其实对测试理解还很浅,很多地方都是硬凑上去,项目也是学生课设级别,没什么含金量 首先是学习建议: 1.系统性了解一个真实工程的框架,有利于你后续提升项目含金量,理解测试的逻辑 2.真正去学一下自动化测试和性能测试 再就是简历本身包装问题: 1.投测试的话就不要说自己独立开发自己测,专注描述自己怎么做测试的 2.项目经历太像套话,很容易让人怀疑你到底真的做过没有,比如并发是具体做了多少并发?自动化脚本是怎么跑兼容性和性能测试的?测试用例写了多少条? 3.教务管理系统一听就是数据库课设作业,含金量不高,不过你可以在原项目基础上重构扩展,比如添加docker容器部署MySQL和Redis,添加消息队列和锁机制防止系统扛不住高并发访问,让它真的像个实际工程 4.技能里性能专项测试没有把握不要乱写,就写你会什么工具就行了,做专项性能测试的都是行业大佬,你要写的话一定要有对应的专项性能测试项目 5.可以在简历里附上项目链接,压缩简历内容的同时提升简历真实性
今天你投了哪些公司?
点赞 评论 收藏
分享
02-28 01:18
已编辑
南昌大学 后端工程师
黑皮白袜臭脚体育生:把开源经历放个人项目上边应该更好,就像大部分人都把实习经历放个人项目上边
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务