zoukankan      html  css  js  c++  java
  • 如何在100万文字的文章中 200ms内 快速提取 替换 上万个关键字

    关键点:

      关键字 组合 成一棵 hash 树  ( 有属性就直接移动指针到下一个字对象, 没有属性就创建子对象, 再移动指针;  第二次循环在子对象看有没这个属性 )

      探测针       标记结束         跳跃      回溯

    var treeSearch = {
            makeTree: function(strKeys) {
                "use strict";
    
                var tblCur = {},
                    tblRoot,
                    key,
                    str_key,
                    Length,
                    j,
                    i
                    ;
                tblRoot = tblCur;
    
                /*一次性 把所以的关键字 都放在 hash tree中
                abc, abd => {     a:{ b: {c: {end:true}, d: {end: true } } }       }
                
                abcd, bc => { a:{b:{c:{d:{end:true}}}},  b:{c:{end:true}}  }
    
                */
                for ( j = strKeys.length - 1; j >= 0; j -= 1) {
    
                    str_key = strKeys[j];
                    Length = str_key.length;
    
                    for ( i = 0; i < Length; i += 1) {
    
                        key = str_key.charAt(i);
    
                        if (tblCur.hasOwnProperty(key)) { //生成子节点
                            tblCur = tblCur[key];
                            
                        } else {
                            //在当前的对象 创建一个子对象
    
                            // 注意 tblRoot 和 tblCur是指向同一个对象 ori, 虽然tblCur移动了
                            // 但还是指向了对象 ori, 所以利用这个tblCur创建的子对象, 仍然是创建在ori上
                            //  而 tblRoot 也指向了 ori, 所以每次tblRoot
                            tblCur[key] = {}
    
                            //移动当前指针到 这个新的子对象
                            tblCur = tblCur[key];
    
                        }
                    }
    
                    tblCur.end = true; //最后一个关键字没有分割符
    
                    // 回溯, tblCur 指针从新指向根节点, 变成了整个对象
                    tblCur = tblRoot;
                }
    
                return tblRoot;
            },
    
            search: function(content, tblRoot) {
                "use strict";
                var tblCur,
                    p_safe = 0,
                    n = content.length,
                    p_tick,
                    match,  //是否找到匹配
                    match_key,
                    match_str,
                    arrMatch = [],  //存储结果
                    arrLength = 0   //arrMatch的长度索引
                    ;
         
                while (p_safe < n) {
                    /*
                        tblRoot { a:{ b: {c: {end:true}, d: {end: true }  } },  { }   }
    
                        n : 10000 
                    */
                    tblCur = tblRoot; //回溯整个对象, 从整个tree从新匹配  
                    p_tick = p_safe;
                    match_str = "";
                    match = false;
    
                    do {
                        
                        /* UCOKsfKBdaqRYQqSYUYjdvDR 
                            match_key :  U
                        */
    
                        //这个是字符串 别人的东西
                        match_key = content.charAt(p_tick);  
    
    
                        // (向前移动) tblCur指针, 指向下一个 深层子对象
                        /**
                            1.  tblCur:  {a: {b:{}, d:{}} }
                            2.  tblCur:  {b:{}, d{} }
                        */
    
                        // tblCur 是关键字自己的 tree, 匹配到别人的一个字, 就继续前移匹配另一个
                        tblCur = tblCur[match_key]
    
                        if (!tblCur) { 
                            
                            //至少说明 以(a) 开头的字母的词组, 从当前位置 往下连续,  是不可能匹配到了   
                            p_safe += 1;   
    
                            // 确认安全后, 小不点 p_safe 移动一个位置
    
                            break;    //直接进入到下一次循环  ---->  out
                        } 
    
    
    
                        match_str += match_key;  //保存  [match]
    
                        p_tick += 1;              // p_safe 小不点,  p_tick 小不点的探测器 (向前移动)
    
                        if (tblCur.end === true) { //
                            match = true;          //说明这几个木板下有坑
                        }
    
                    } while (true);
    
    
    
    
    
         
                    if (match === true) { //最大匹配
                        
    
                        /**
                          把找到的 标记起来
                        **/
                        arrMatch[arrLength] = { //增强可读性
                            key: match_str,
                            begin: p_safe - 1,
                            end: p_tick
                        };
                        arrLength += 1;
    
                        
    
    
                        p_safe = p_tick;   // 小不点直接跳过坑
                    }
    
    
                }
                return arrMatch;
            }
        }
    
        function test(strContent, strKeys) {
    
            var s1 = new Date();
    
            var arrMatch, item,
                tblRoot = treeSearch.makeTree(strKeys),
                t = new Date();
            
            console.log( t  -  s1)
    
            for (var i = 0; i < strContent.length; i++) {
                  item = strContent[i];
    
                  arrMatch = treeSearch.search(item, tblRoot);
    
            }
           
             
          
            console.log("time is: " + (new Date() - t) + "ms");
         
            
         
            console.dir(arrMatch);
        }
    
        var s = (function() {
            var Things = ['汉', '
    ', '小', '大', '海', '能'];
            var s = "";
            var arr = []
           
            for (var i = 1000000; i >= 0; i--) {
    
                 s += Things[parseInt(Math.random() * Things.length) % Things.length]
    
                if( i % 50 == 0 ){
                    arr.push(s);
                    s = '';
                }
               
            };
    
            return arr;
    
        })()
    
        test(s, ["汉能",  "abcd", "bc", 'lala']);
    View Code
     var treeSearch = {
            makeTree: function(strKeys) {
                "use strict";
    
                var tblCur = {},
                    tblRoot,
                    key,
                    str_key,
                    Length,
                    j,
                    i
                    ;
                tblRoot = tblCur;
    
                /*一次性 把所以的关键字 都放在 hash tree中
                abc, abd => {     a:{ b: {c: {end:true}, d: {end: true } } }       }
                
                abcd, bc => { a:{b:{c:{d:{end:true}}}},  b:{c:{end:true}}  }
    
                */
                for ( j = strKeys.length - 1; j >= 0; j -= 1) {
    
                    str_key = strKeys[j];
                    Length = str_key.length;
    
                    for ( i = 0; i < Length; i += 1) {
    
                        key = str_key.charAt(i);
    
                        if (tblCur.hasOwnProperty(key)) { //生成子节点
                            tblCur = tblCur[key];
                        } else {
                            //在当前的对象 创建一个子对象
    
                            // 注意 tblRoot 和 tblCur是指向同一个对象 ori, 虽然tblCur移动了
                            // 但还是指向了对象 ori, 所以利用这个tblCur创建的子对象, 仍然是创建在ori上
                            //  而 tblRoot 也指向了 ori, 所以每次tblRoot
                            tblCur[key] = {}
    
                            //移动当前指针到 这个新的子对象
                            tblCur = tblCur[key];
    
                        }
                    }
    
                    tblCur.end = true; //最后一个关键字没有分割符
    
                    // 回溯, tblCur 指针从新指向根节点, 变成了整个对象
                    tblCur = tblRoot;
                }
    
                return tblRoot;
            },
    
            search: function(content, tblRoot) {
                "use strict";
                var tblCur,
                    p_star = 0,
                    n = content.length,
                    p_end,
                    match,  //是否找到匹配
                    match_key,
                    match_str,
                    arrMatch = [],  //存储结果
                    arrLength = 0   //arrMatch的长度索引
                    ;
         
                while (p_star < n) {
                    /*
                        tblRoot { a:{ b: {c: {end:true}, d: {end: true }  } },  { }   }
    
                        n : 10000 
                    */
                    tblCur = tblRoot; //回溯至根部  
                    p_end = p_star;
                    match_str = "";
                    match = false;
    
                    do {
                        
                        /* UCOKsfKBdaqRYQqSYUYjdvDR 
                            match_key :  U
                        */
                        match_key = content.charAt(p_end);  
    
    
                        // (向前移动) tblCur指针, 指向下一个 深层子对象
                        tblCur = tblCur[match_key]
    
                        if (!tblCur) { 
                            
                            //至少说明 以(a) 开头的字母的词组, 在当前位置是不可能匹配到了   
                            p_star += 1;   
                            // 确认安全后, 小不点 p_start 移动一个位置
    
                            break;    //直接进入到下一次循环  ---->  out
                        } 
    
                        match_str += match_key;  //保存  [match]
    
                        p_end += 1;              // p_star 小不点,  p_end 小不点的探测器 (向前移动)
    
                        if (tblCur.end === true) { //
                            match = true;          //说明这几个木板下有坑
                        }
    
                    } while (true);
         
                    if (match === true) { //最大匹配
                        
    
                        /**
                          把找到的 标记起来
                        **/
                        arrMatch[arrLength] = { //增强可读性
                            key: match_str,
                            begin: p_star - 1,
                            end: p_end
                        };
                        arrLength += 1;
    
                        
    
    
                        p_star = p_end;   // 小不点直接跳过坑
                    }
    
    
                }
                return arrMatch;
            }
        }
    
        function test(strContent, strKeys) {
    
            var s1 = new Date();
    
            var arrMatch, item,
                tblRoot = treeSearch.makeTree(strKeys),
                t = new Date();
            
            console.log( t  -  s1)
    
            for (var i = 0; i < strContent.length; i++) {
                  item = strContent[i];
    
                  arrMatch = treeSearch.search(item, tblRoot);
    
            }
           
             
          
            console.log("time is: " + (new Date() - t) + "ms");
         
            
         
            console.dir(arrMatch);
        }
    
        var s = (function() {
            var Things = ['汉', '
    ', '小', '大', '海', '能'];
            var s = "";
            var arr = []
           
            for (var i = 1000000; i >= 0; i--) {
    
                 s += Things[parseInt(Math.random() * Things.length) % Things.length]
    
                if( i % 50 == 0 ){
                    arr.push(s);
                    s = '';
                }
               
            };
    
            return arr;
    
        })()
    
        test(s, ["汉能",  "abcd", "bc", 'lala']);
    View Code

    链接  需要使用树算法, 

    var treeSearch = {
        makeTree: function(strKeys) {
            "use strict";
            var tblCur = {},
                tblRoot,
                key,
                str_key,
                Length,
                j,
                i
                ;
            tblRoot = tblCur;
            for ( j = strKeys.length - 1; j >= 0; j -= 1) {
                str_key = strKeys[j];
                Length = str_key.length;
                for ( i = 0; i < Length; i += 1) {
                    key = str_key.charAt(i);
                    if (tblCur.hasOwnProperty(key)) { //生成子节点
                        tblCur = tblCur[key];
                    } else {
                        tblCur = tblCur[key] = {};
                    }
                }
                tblCur.end = true; //最后一个关键字没有分割符
                tblCur = tblRoot;
            }
            return tblRoot;
        },
        search: function(content, tblRoot) {
            "use strict";
            var tblCur,
                p_star = 0,
                n = content.length,
                p_end,
                match,  //是否找到匹配
                match_key,
                match_str,
                arrMatch = [],  //存储结果
                arrLength = 0   //arrMatch的长度索引
                ;
     
            while (p_star < n) {
                tblCur = tblRoot; //回溯至根部
                p_end = p_star;
                match_str = "";
                match = false;
                do {
                    match_key = content.charAt(p_end);
                    if (!(tblCur = tblCur[match_key])) { //本次匹配结束
                        p_star += 1;
                        break;
                    }else{
                        match_str += match_key;
                    }
                    p_end += 1;
                    if (tblCur.end === true) //是否匹配到尾部  //找到匹配关键字
                    {
                        match = true;
                    }
                } while (true);
     
                if (match === true) { //最大匹配
                    arrMatch[arrLength] = { //增强可读性
                        key: match_str,
                        begin: p_star - 1,
                        end: p_end
                    };
                    arrLength += 1;
                    p_star = p_end;
                }
            }
            return arrMatch;
        }
    };
    View Code
    function test(strContent, strKeys) {
        var arrMatch,
            tblRoot = treeSearch.makeTree(strKeys),
            t = new Date();
     
     
        arrMatch = treeSearch.search(strContent, tblRoot);
     
        console.log("time is: " + (new Date() - t) + "mm");
     
        console.log(arrMatch);
    }
    var s = (function() {
        var Things = [' ', '
    ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
        var s = "";
        for (var i = 1000000; i >= 0; i--) {
            s += Things[parseInt(Math.random() * Things.length) % Things.length]
        };
        return s;
    })()
    test(s, ["abc", "efge", "fun", "tree"]);
    View Code
     var treeSearch = {
            makeTree: function(strKeys) {
                "use strict";
    
                var tblCur = {},
                    tblRoot,
                    key,
                    str_key,
                    Length,
                    j,
                    i
                    ;
                tblRoot = tblCur;
    
                for ( j = strKeys.length - 1; j >= 0; j -= 1) {
    
                    str_key = strKeys[j];
                    Length = str_key.length;
    
                    for ( i = 0; i < Length; i += 1) {
    
                        key = str_key.charAt(i);
                        if (tblCur.hasOwnProperty(key)) { //生成子节点
                            tblCur = tblCur[key];
                        } else {
                            //在当前的对象 创建一个子对象
                            tblCur[key] = {}
    
                            //移动当前指针到 这个新的子对象
                            tblCur = tblCur[key];
    
                        }
                    }
    
                    tblCur.end = true; //最后一个关键字没有分割符
    
                    tblCur = tblRoot;
                }
    
                return tblRoot;
            },
    
            search: function(content, tblRoot) {
                "use strict";
                var tblCur,
                    p_star = 0,
                    n = content.length,
                    p_end,
                    match,  //是否找到匹配
                    match_key,
                    match_str,
                    arrMatch = [],  //存储结果
                    arrLength = 0   //arrMatch的长度索引
                    ;
         
                while (p_star < n) {
                    /*
                        tblRoot { a:{ b: {c: {end:true}, d: {end: true }  } },  { }   }
    
                        n : 10000 
                    */
                    tblCur = tblRoot; //回溯至根部  
                    p_end = p_star;
                    match_str = "";
                    match = false;
    
                    do {
                        
                        /* UCOKsfKBdaqRYQqSYUYjdvDR 
                            match_key :  U
                        */
                        match_key = content.charAt(p_end);  
    
                        if (!(tblCur = tblCur[match_key])) { // (向前移动) tblCur指针, 指向下一个 深层子对象
                           
                            p_star += 1;   // 确认安全后, 小不点 p_start 移动一个位置
    
                            break;    //直接进入到下一次循环  ---->  out
                        } 
    
                        match_str += match_key;  //保存  [match]
    
                        p_end += 1;              // p_star 小不点,  p_end 小不点的探测器 (向前移动)
    
                        if (tblCur.end === true) { //
                            match = true;          //说明这几个木板下有坑
                        }
    
                    } while (true);
         
                    if (match === true) { //最大匹配
                        
    
                        /**
                          把找到的 标记起来
                        **/
                        arrMatch[arrLength] = { //增强可读性
                            key: match_str,
                            begin: p_star - 1,
                            end: p_end
                        };
                        arrLength += 1;
    
                        
    
    
                        p_star = p_end;   // 小不点直接跳过坑
                    }
    
    
                }
                return arrMatch;
            }
        }
    
        function test(strContent, strKeys) {
            var arrMatch,
                tblRoot = treeSearch.makeTree(strKeys),
                t = new Date();
          
            arrMatch = treeSearch.search(strContent, tblRoot);
             
          
            console.log("time is: " + (new Date() - t) + "mm");
         
            
         
            console.dir(arrMatch[0]);
        }
    
        var s = "abcd汉能abcd"; /*(function() {
            var Things = [' ', '
    ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
            var s = "";
           
            for (var i = 1000000; i >= 0; i--) {
                s += Things[parseInt(Math.random() * Things.length) % Things.length]
            };
    
            return s;
    
        })()*/
    
        test(s, ["汉能",  "abd"]);
    View Code
  • 相关阅读:
    Flask程序相关配置加载的三种方式
    Redis数据库在windows系统下的安装及使用
    Redis数据库介绍
    python中模块的制作
    4.ORM框架的查询
    3.ORM框架一对多的关系及使用
    2.ORM框架添加,修改,删除操作
    1.ORM介绍,基本配置及通过ORM框架创建表
    4.集合
    3.字典
  • 原文地址:https://www.cnblogs.com/dhsz/p/6564243.html
Copyright © 2011-2022 走看看