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
  • 相关阅读:
    Python for Infomatics 第14章 数据库和SQL应用四(译)
    展望2017
    bing的简单英文字典工具
    自我安慰
    Python for Infomatics 第14章 数据库和SQL应用三(译)
    Python for Infomatics 第14章 数据库和SQL应用二(译)
    Python for Infomatics 第14章 数据库和SQL应用一(译)
    希望父亲早日恢复
    Python for Infomatics 第13章 网页服务四(译)
    Python for Infomatics 第13章 网页服务三(译)
  • 原文地址:https://www.cnblogs.com/dhsz/p/6564243.html
Copyright © 2011-2022 走看看