AC自动机

匿名 (未验证) 提交于 2019-12-02 21:53:52

1.根据字符构造trie树 2.构建失败匹配指针    1.根节点的所以一代子孩子失败指针都指向root    2.子节点匹配失败时,找到父节点的失败指针,找不到就一直找,直到找到root还匹配不到,直接指向root 3.文本串匹配    1.如果已经匹配到完整的模式串,根据失败指针切换线路继续向下查找    2.如果还没有匹配完,那么就向下匹配 
class ACNode {     constructor(data){         this.data = data         this.children = new Map()         this.isEndingChar = false         this.length = 0         this.fail = null     } }  class ACTree {     constructor(){         this.root = new ACNode('/')     }     insert(text){         let node = this.root         for(let char of text){             if(!node.children.get(char)){                 node.children.set(char,new ACNode(char))             }             node = node.children.get(char)         }         node.isEndingChar = true         node.length = text.length        }     buildFailurePointer(){         let root = this.root         let queue = []         queue.push(root)          while(queue.length > 0){             let parentNode = queue.shift()             for(let childNode of parentNode.children.values()){                 if(!childNode){                     continue                 }                 //如果现在还在树的第一层                 if(parentNode == root){                     //所有子节点的失败指针都指向root                     childNode.fail = root                 } else {                     let grandFatherNode = parentNode.fail                     while(grandFatherNode){                         let failNode = grandFatherNode.children.get(childNode.data)                         if(failNode){                             childNode.fail = failNode                             break                         }                         grandFatherNode = grandFatherNode.fail                     }                     if(!grandFatherNode){                         childNode.fail = root                     }                 }                                  queue.push(childNode)             }         }             }     match(text){       let root = this.root       let len = text.length       let currentNode = root              for( let i = 0; i < len; i++ ){          let char = text[i]           while(!currentNode.children.get(char) && currentNode !== root){              //换线匹配             currentNode = currentNode.fail          }           currentNode = currentNode.children.get(char)          if(!currentNode){              //如果currentNode没有值,就重新回到root节点             currentNode = root          }          let tmp = currentNode          while(tmp != root){              if(tmp.isEndingChar === true){                 console.log(`from ${i - tmp.length + 1} length: ${tmp.length} str: ${text.substr(i - currentNode.length + 1,currentNode.length)}`)              }              tmp = tmp.fail          }       }     } }  function match(text,patterns){     let automata = new ACTree();     for(let pattern of patterns){         automata.insert(pattern);     }     automata.buildFailurePointer();     automata.match(text); }  let patterns = ["at", "art", "oars", "soar"]; let text = "soarsoars"; match(text, patterns);  let patterns2 = ["Fxtec Pro1", "谷歌Pixel"]; let text2 = "一家总部位于伦敦的公司Fxtex在MWC上就推出了一款名为Fxtec Pro1的手机,该机最大的亮点就是采用了侧滑式全键盘设计。DxOMark年度总榜发布 华为P20 Pro/谷歌Pixel 3争冠"; match(text2, patterns2);
文章来源: AC自动机
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!