论坛首页 综合技术论坛

两个大数据量处理的问题.被鄙视了呜呜

浏览 27947 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-09-13  
tmj_159 写道
第一题 hash 到小文件,统计到小文件,将小文件归并排序


根据词的拼音首字母 分26个文件存  ?
0 请登录后投票
   发表时间:2011-09-13  
Reset 写道
tmj_159 写道
第一题 hash 到小文件,统计到小文件,将小文件归并排序


根据词的拼音首字母 分26个文件存  ?


不一定固定按照第首字母,也可以按前N个字母或任意段。或者使用多级小文件。
当数据量比内存大的时候,必然要转储的。剩下的解决的就是转储时查找的效率问题。
0 请登录后投票
   发表时间:2011-09-13  
第二个你都会了 第一个为什么你不会呢?用正则呀··当初笔试也遇到过这个类似的题,印象比较深。
0 请登录后投票
   发表时间:2011-09-13  
可以构造一棵树. 树的每个节点是一个字母.对于每个单词在树上都有一个唯一的路径.回溯这个路径可以得到完整的单词.这些路径不会太多,不超过几万个.每次解析一个单词都在这个树中查找,如果找不到就构建它,如果找到就在叶节点加1. 比如AB,ABC, ABD, AC
构造是下面的树.  得到这个树后可以遍历这颗树来比较频率最高的单词.
    A
  /  \
B    C
/  \
C   D
1 请登录后投票
   发表时间:2011-09-14  
1亿个词扔到数据库里,select count    order by 一下就出来了
0 请登录后投票
   发表时间:2011-09-14   最后修改:2011-09-14
cdcx 写道
可以构造一棵树. 树的每个节点是一个字母.对于每个单词在树上都有一个唯一的路径.回溯这个路径可以得到完整的单词.这些路径不会太多,不超过几万个.每次解析一个单词都在这个树中查找,如果找不到就构建它,如果找到就在叶节点加1. 比如AB,ABC, ABD, AC
构造是下面的树.  得到这个树后可以遍历这颗树来比较频率最高的单词.
    A
  /  \
B    C
/  \
C   D

很靠谱,+1,尝试着实现了一下

public class WordTree {
    
    public static void main(String[] args) {
        WordTree t = new WordTree();
        String[] ss = {"asdf", "asdf", "as", "a"};
        for(String s : ss) {
            t.accept(s);
        }
        CharNode cNode = t.getMaxNode();
        System.out.println(cNode.num + " : " + cNode.getS());
    }
    
    /**
     * 接收并处理一条新纪录
     * @author		lzxz
     * @param s		
     */
    public void accept(String s) {
        this.accept((CharSequence)s.toUpperCase());
    }
    
    /**
     * 得到最大数量节点
     * @author		lzxz
     * @return		
     */
    public CharNode getMaxNode() {
        int maxNum = 0;
        CharNode maxNode = null;
        for(CharNode cNode : list) {
            if(cNode.num > maxNum) {
                maxNode = cNode;
                maxNum = cNode.num;
            }
        }
        return maxNode;
    }
    
    /**
     * 得到最大数量节点,要求必须全部大写
     * @author		lzxz
     * @param cs		
     */
    public void accept(CharSequence cs){
        this.root.accept(cs);
    }
    
    private CharNode root = new CharNode(null, '$');
    private final List<CharNode> list = new ArrayList<CharNode>();
    
    private class CharNode {
        private char c;
        private int num;
        private CharNode parent = null;
        
        private Map<Character, CharNode> next;
        
        /**
         * 得到到达本路径的字符串全量
         * @author		lzxz
         * @return		
         */
        private String getS() {
            if(this.parent == null) {
                return String.valueOf(c);
            }
            
            return this.parent.getS() + c;
        }
        /**
         * 接收并处理一条新纪录
         * @author		lzxz
         * @param cs		
         */
        private void accept(CharSequence cs) {
            CharNode node = next.get(cs.charAt(0));
            if(node == null) {
                node = new CharNode(this, cs.charAt(0));
                next.put(cs.charAt(0), node);
                list.add(node);
            }
            
            if(cs.length() == 1){
                node.num ++;
            } else {
                node.accept(cs.subSequence(1, cs.length()));
            }
        }
        
        /**  
         * 指定参数构造CharNode实例。
         * @param parent
         * @param c   
         */
        public CharNode(CharNode parent, char c){
            num = 0;
            this.parent = parent;
            this.c = c;
            next = new HashMap<Character, CharNode>();
        }
    }
}

1 请登录后投票
   发表时间:2011-09-14  
oaklet 写道
1亿个词扔到数据库里,select count    order by 一下就出来了

数据库没那么强,1亿条记录order by指不定得跑几个小时呢
0 请登录后投票
   发表时间:2011-09-14  
像lucene里面的记录方式就是   1. 分词 2.把对应的词条加入文档,文档里面会记录对应的词的索引条数,  如果真正意义来说要去实时统计的话,不是通过计算,而是直接读取词条记录的条数。 
0 请登录后投票
   发表时间:2011-09-14  
lzxz1234 写道
cdcx 写道
可以构造一棵树. 树的每个节点是一个字母.对于每个单词在树上都有一个唯一的路径.回溯这个路径可以得到完整的单词.这些路径不会太多,不超过几万个.每次解析一个单词都在这个树中查找,如果找不到就构建它,如果找到就在叶节点加1. 比如AB,ABC, ABD, AC
构造是下面的树.  得到这个树后可以遍历这颗树来比较频率最高的单词.
    A
  /  \
B    C
/  \
C   D

很靠谱,+1,尝试着实现了一下

public class WordTree {
    
    public static void main(String[] args) {
        WordTree t = new WordTree();
        String[] ss = {"asdf", "asdf", "as", "a"};
        for(String s : ss) {
            t.accept(s);
        }
        CharNode cNode = t.getMaxNode();
        System.out.println(cNode.num + " : " + cNode.getS());
    }
    
    /**
     * 接收并处理一条新纪录
     * @author		lzxz
     * @param s		
     */
    public void accept(String s) {
        this.accept((CharSequence)s.toUpperCase());
    }
    
    /**
     * 得到最大数量节点
     * @author		lzxz
     * @return		
     */
    public CharNode getMaxNode() {
        int maxNum = 0;
        CharNode maxNode = null;
        for(CharNode cNode : list) {
            if(cNode.num > maxNum) {
                maxNode = cNode;
                maxNum = cNode.num;
            }
        }
        return maxNode;
    }
    
    /**
     * 得到最大数量节点,要求必须全部大写
     * @author		lzxz
     * @param cs		
     */
    public void accept(CharSequence cs){
        this.root.accept(cs);
    }
    
    private CharNode root = new CharNode(null, '$');
    private final List<CharNode> list = new ArrayList<CharNode>();
    
    private class CharNode {
        private char c;
        private int num;
        private CharNode parent = null;
        
        private Map<Character, CharNode> next;
        
        /**
         * 得到到达本路径的字符串全量
         * @author		lzxz
         * @return		
         */
        private String getS() {
            if(this.parent == null) {
                return String.valueOf(c);
            }
            
            return this.parent.getS() + c;
        }
        /**
         * 接收并处理一条新纪录
         * @author		lzxz
         * @param cs		
         */
        private void accept(CharSequence cs) {
            CharNode node = next.get(cs.charAt(0));
            if(node == null) {
                node = new CharNode(this, cs.charAt(0));
                next.put(cs.charAt(0), node);
                list.add(node);
            }
            
            if(cs.length() == 1){
                node.num ++;
            } else {
                node.accept(cs.subSequence(1, cs.length()));
            }
        }
        
        /**  
         * 指定参数构造CharNode实例。
         * @param parent
         * @param c   
         */
        public CharNode(CharNode parent, char c){
            num = 0;
            this.parent = parent;
            this.c = c;
            next = new HashMap<Character, CharNode>();
        }
    }
}





这个问题我也考虑过..
但是怕出现如下场景


用户查询100次中国


然后用户查询了100000次中国人


于是中国就变成100100次了
0 请登录后投票
   发表时间:2011-09-14  
ansjsun 写道
lzxz1234 写道
cdcx 写道
可以构造一棵树. 树的每个节点是一个字母.对于每个单词在树上都有一个唯一的路径.回溯这个路径可以得到完整的单词.这些路径不会太多,不超过几万个.每次解析一个单词都在这个树中查找,如果找不到就构建它,如果找到就在叶节点加1. 比如AB,ABC, ABD, AC
构造是下面的树.  得到这个树后可以遍历这颗树来比较频率最高的单词.
    A
  /  \
B    C
/  \
C   D

很靠谱,+1,尝试着实现了一下

public class WordTree {
    
    public static void main(String[] args) {
        WordTree t = new WordTree();
        String[] ss = {"asdf", "asdf", "as", "a"};
        for(String s : ss) {
            t.accept(s);
        }
        CharNode cNode = t.getMaxNode();
        System.out.println(cNode.num + " : " + cNode.getS());
    }
    
    /**
     * 接收并处理一条新纪录
     * @author		lzxz
     * @param s		
     */
    public void accept(String s) {
        this.accept((CharSequence)s.toUpperCase());
    }
    
    /**
     * 得到最大数量节点
     * @author		lzxz
     * @return		
     */
    public CharNode getMaxNode() {
        int maxNum = 0;
        CharNode maxNode = null;
        for(CharNode cNode : list) {
            if(cNode.num > maxNum) {
                maxNode = cNode;
                maxNum = cNode.num;
            }
        }
        return maxNode;
    }
    
    /**
     * 得到最大数量节点,要求必须全部大写
     * @author		lzxz
     * @param cs		
     */
    public void accept(CharSequence cs){
        this.root.accept(cs);
    }
    
    private CharNode root = new CharNode(null, '$');
    private final List<CharNode> list = new ArrayList<CharNode>();
    
    private class CharNode {
        private char c;
        private int num;
        private CharNode parent = null;
        
        private Map<Character, CharNode> next;
        
        /**
         * 得到到达本路径的字符串全量
         * @author		lzxz
         * @return		
         */
        private String getS() {
            if(this.parent == null) {
                return String.valueOf(c);
            }
            
            return this.parent.getS() + c;
        }
        /**
         * 接收并处理一条新纪录
         * @author		lzxz
         * @param cs		
         */
        private void accept(CharSequence cs) {
            CharNode node = next.get(cs.charAt(0));
            if(node == null) {
                node = new CharNode(this, cs.charAt(0));
                next.put(cs.charAt(0), node);
                list.add(node);
            }
            
            if(cs.length() == 1){
                node.num ++;
            } else {
                node.accept(cs.subSequence(1, cs.length()));
            }
        }
        
        /**  
         * 指定参数构造CharNode实例。
         * @param parent
         * @param c   
         */
        public CharNode(CharNode parent, char c){
            num = 0;
            this.parent = parent;
            this.c = c;
            next = new HashMap<Character, CharNode>();
        }
    }
}





这个问题我也考虑过..
但是怕出现如下场景


用户查询100次中国


然后用户查询了100000次中国人


于是中国就变成100100次了



不好意思我仔细看了下代码..仿佛是实现了..我没有考虑可以回溯..不过内存占用率应该还是比较高的...但是还是比较靠谱的...我之前认为实现的办法是..先hash后存入map...key是单词..value是数量....
最后迭代出结果..不过貌似你这个比较好.我试试哈
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics