2021-02-21:手写代码:高性能路由,也就是一个字符串和多个匹配串进行模糊匹配。一个数组arr里是["a","moonfdd"],字符串"moonfdd"能匹配到,理由是arr里有。字符串"xayy"也能匹配到,理由是arr里的"a",第1个星对应"x",第2个星对应"yy"。

福哥答案2021-02-21:

1.前缀树。字符匹配和星号匹配。abcd和abcd,当左c和右对应的时候,下一步分两种情况,左d和右*对应,左c和右c对应。有代码。

2.ACOK算法。当时和面试官聊的时候,面试官说了ACOK算法,但这个算法在网上没找到。百度了一番,感觉就是Aho-Corasick automaton算法,也就是AC自动机。AC自动机,没找到解法,所以没代码。

代码用golang编写,代码如下:

package main

import "fmt"

func main() {
fmt.Println("力扣208 测试")
trie := Constructor()
trie.Insert("apple")
trie.Search("apple") // 返回 true
trie.Search("app") // 返回 false
trie.StartsWith("app") // 返回 true
trie.Insert("app")
trie.Search("app") // 返回 true
fmt.Println("--------------------")
fmt.Println("高性能路由 测试")
ret := ""
ret = RouteMatching("fudada", []string{"fudada*"})
fmt.Println("ret = ", ret)
ret = RouteMatching("fudada", []string{"fu******da*"})
fmt.Println("ret = ", ret)
ret = RouteMatching("fudada", []string{"fudada**"})
fmt.Println("ret = ", ret) } type TrieNode struct {
pass int
end int
nextMap map[byte]*TrieNode
}
type Trie struct {
root *TrieNode
} /** Initialize your data structure here. */
func Constructor() Trie {
return Trie{root: &TrieNode{nextMap: make(map[byte]*TrieNode)}}
} /** Inserts a word into the trie. */
func (this *Trie) Insert(word string) {
wordLen := len(word)
if wordLen == 0 {
return
}
node := this.root
node.pass++
for i := 0; i < wordLen; i++ { // 从左往右遍历字符
if node.nextMap[word[i]] == nil {
node.nextMap[word[i]] = &TrieNode{nextMap: make(map[byte]*TrieNode)}
}
node = node.nextMap[word[i]]
node.pass++
}
node.end++
} /** Returns if the word is in the trie. */
func (this *Trie) Search(word string) bool {
wordLen := len(word)
if wordLen == 0 {
fmt.Println(false)
return false
}
node := this.root
for i := 0; i < wordLen; i++ { // 从左往右遍历字符
if node.nextMap[word[i]] == nil {
fmt.Println(false)
return false
}
node = node.nextMap[word[i]]
}
fmt.Println(node.end > 0)
return node.end > 0
} /** Returns if there is any word in the trie that starts with the given prefix. */
func (this *Trie) StartsWith(prefix string) bool {
word := prefix
wordLen := len(word)
if wordLen == 0 {
fmt.Println(false)
return false
}
node := this.root
for i := 0; i < wordLen; i++ { // 从左往右遍历字符
if node.nextMap[word[i]] == nil {
fmt.Println(false)
return false
}
node = node.nextMap[word[i]]
}
fmt.Println(node.pass > 0)
return node.pass > 0
} func RouteMatching(url string, fuzzyMatches []string) string {
fuzzyMatchesLen := len(fuzzyMatches)
if fuzzyMatchesLen == 0 && len(url) == 0 {
return ""
}
trie := Constructor()
for i := 0; i < fuzzyMatchesLen; i++ {
trie.Insert(fuzzyMatches[i])
}
return process(url, 0, trie.root, "")
} func process(url string, index int, root *TrieNode, retPre string) string {
urlLen := len(url)
if index >= urlLen {
if root.end > 0 {
return retPre
} else {
if root.nextMap['*'] != nil {
return process(url, index, root.nextMap['*'], retPre+"*")
}
return ""
}
}
ret := ""
//1.匹配字符
if root.nextMap[url[index]] != nil {
ret = process(url, index+1, root.nextMap[url[index]], retPre+url[index:index+1])
if ret != "" {
return ret
}
}
//2.匹配*
if root.nextMap['*'] != nil {
ret = process(url, index, root.nextMap['*'], retPre+"*")
if ret != "" {
return ret
}
ret = process(url, index+1, root, retPre)
if ret != "" {
return ret
}
}
return ret
}

执行结果如下:


左神前缀树java代码

评论

2021-02-21:手写代码:高性能路由,也就是一个字符串和多个匹配串进行模糊匹配。一个数组arr里是["*a*","moonfdd"],字符串"moonfdd"能匹配到,理由是arr里有。字符串"xayy"也能匹配到,理由是arr里的"*a*",第1个星对应"x",第2个星对应"yy"。的更多相关文章

  1. 2019前端面试系列——JS高频手写代码题

    实现 new 方法 /* * 1.创建一个空对象 * 2.链接到原型 * 3.绑定this值 * 4.返回新对象 */ // 第一种实现 function createNew() { let obj ...

  2. ClownFish:比手写代码还快的通用数据访问层

    http://www.cnblogs.com/fish-li/archive/2012/07/17/ClownFish.html 阅读目录 开始 ClownFish是什么? 比手写代码还快的执行速度 ...

  3. 手写代码自动实现自动布局,即Auto Layout的使用

    手写代码自动实现自动布局,即Auto Layout的使用,有需要的朋友可以参考下. 这里要注意几点: 对子视图的约束,若是基于父视图,要通过父视图去添加约束. 对子视图进行自动布局调整,首先对UIVi ...

  4. 如果选择构建ui界面方式,手写代码,xib和StoryBoard间的博弈

    代码手写UI这种方法经常被学院派的极客或者依赖多人合作的大型项目大规模使用. 大型多人合作项目使用代码构建UI,主要是看中纯代码在版本管理时的优势,检查追踪改动以及进行代码合并相对容易一些. 另外,代 ...

  5. .netER的未来路,关于基础是否重要和应该自己手写代码吗?

    http://www.cnblogs.com/onepiece_wang/p/5558341.html#!comments 引用"基础知识的学习,一开始可能是背书,但是在后续若干年的工作过程 ...

  6. 手写代码UI,xib和StoryBoard间的的优劣比较

    在UI制作方面,逐渐分化三种主要流派:使用代码手写UI:使用单个xib文件组织viewController或者view:使用StoryBoard来通过单个或很少的几个文件构建UI.三种方式各有优劣,也 ...

  7. UI到底应该用xib/storyboard完成,还是用手写代码来完成?

    UI到底应该用xib/storyboard完成,还是用手写代码来完成? 文章来源:http://blog.csdn.net/libaineu2004/article/details/45488665 ...

  8. java 手写 jvm高性能缓存

    java 手写 jvm高性能缓存,键值对存储,队列存储,存储超时设置 缓存接口 package com.ws.commons.cache; import java.util.function.Func ...

  9. Appium初始化设置:手写代码连接手机、appium-desktop连接手机

    一.包名获取的三种方式 1)找开发要2)mac使用命令:adb logcat | grep START win使用命令:adb logcat | findstr START 或者可以尝试使用第3条命令 ...

  10. gcd手写代码及STL中的使用方法

    一.手写代码 inline int gcd(int x,int y){ if(y==0) return x; else return(gcd(y,x%y)); } 二.STL中的使用方法 注:在STL ...

随机推荐

  1. Windows软件堆栈溢出(stack overflow)的一些解决方法

    欢迎访问我的个人博客:xie-kang.com 原文地址 Windows平台下,有三种方法调整堆栈大小(适用于MSVC编译器): 1)添加编译参数:/F size  #其中size的单位是byte可设 ...

  2. typescript开发vue项目二次封装的axios用return Promise.reject(error) 返回异常,提示[Vue warn]: Error in v-on handler (Promise/async)

    二次封装axios时刻意服务端模拟了延迟返回数据的场景,用return Promise.reject(error) 返回异常,报如下错误, [Vue warn]: Error in v-on hand ...

  3. MarkDown基本用法学习

    一级标题 语法:# +内容 二级标题1 语法:## +内容 二级标题2 三级标题 语法:### +内容 字体 加粗 语法:** +内容+ **(中间无空格) 效果:粗体 斜体 语法 * +内容+ *( ...

  4. rename基本操作

    电脑是Macbook, 用Homebrew先安装rename. 如果没安装Homebrew 直接复制到terminal中回车, 时间稍长. ruby -e "$(curl -fsSL htt ...

  5. JDK8:Lambda表达式操作List集合

    JDK8的流对list的处理提供了很大的方便,特别是做报表的时候才能真正体现出来这个功能的强大:结合日常使用过程,有两个体会:一个是减少了数据库连接,最忌讳在循环中进行数据查询,特别是嵌套多层循环的时 ...

  6. 4.错误代码C1083

    有的时候在VS中遇到的error C1083: 无法打开**: " * .*": No such file or directory的错误,这里总结了我遇到过的情况: 错误 C10 ...

  7. 当transcational遇上synchronized

    工作当中经常会遇到既需要开启事务管理,同时也需要同步保证线程安全的场景. 比如一个方法 @Transactional public synchronized void test(){ // } 不知道 ...

  8. 面向Web开发人员的Linux实用入门

    从 web 开发的视角说一下在使用 Linux 时遇到的问题,主要是针对操作本身,因为指令在网上都可以查到,不会深入原理,但尽量实用. 基础认知 为什么使用 Linux 最初我使用 Linux 是因为 ...

  9. 支付回调MQ消息的幂等处理及MD5字符串es中的使用及支付宝预授权完成

    支付回调MQ消息的幂等处理及MD5字符串es中的使用及支付宝预授权完成 1.幂等的处理,根据对象的转json 转md5作为key,退款的处理 控制发送端?业务上比较难控制.支付异步通知,退款有同步通知 ...

  10. 用 Go 剑指 Offer 09. 用两个栈实现队列

    用两个栈实现一个队列.队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能.(若队列中没有元素,deleteHea ...