码迷,mamicode.com
首页 > 编程语言 > 详细

java实现fp-growth算法

时间:2019-06-28 09:14:26      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:eva   +=   提升   lsp   lang   步骤   algorithm   代码   near   

最近公司项目上用到频繁项发现算法,于是就用java实现了一个fp-growth算法实现。

环境说明 版本说明 备注
操作系统 debian 9 无 
jdk openjdk 1.8 无 

关于fp-growth算法的原理请参考:

https://www.cnblogs.com/pinard/p/6307064.html 和《机器学习实战》。

FpTreeNode类

package com.slyk.sdp.algorithms.externalAlgorithms.fpTree;

import java.util.ArrayList;
import java.util.List;

/**
 * 描述:fpTree树节点
 * 
 * @param <T>
 *
 * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
 * @created on 2019年5月23日,下午8:01:46
 */
public class FpTreeNode<T> {
    /**
     * 当前节点频繁度
     */
    private long count = 0;
    
    /**
     * 节点内容值
     */
    private T nodeVal;
    
    /**
     * 父类节点
     */
    private FpTreeNode<T> parent = null;
    
    /**
     * 当前节点子节点
     */
    private List<FpTreeNode<T>> children = null;
    
    /**
     * helper
     */
    private FpTreeHelper<T> helper = null;
    
    public FpTreeNode(long count, T nodeVal, FpTreeNode<T> parent, List<FpTreeNode<T>> children,
            FpTreeHelper<T> helper) {
        super();
        this.count = count;
        this.nodeVal = nodeVal;
        this.parent = parent;
        this.children = children;
        this.helper = helper;
    }

    /**
     * 描述:添加子节点
     *
     * @param child
     * @return 被添加的子节点
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月23日,下午7:33:13
     */
    public FpTreeNode<T> addChild(FpTreeNode<T> child) {
        if (this.getChildren() == null) {
            children = new ArrayList<FpTreeNode<T>>();
        }
        child.setParent(this);
        this.children.add(child);
        return child;
    }
    
    /**
     * 描述:向当前节点添加路径
     * <br/>
     * List结构数据前一项为后一项数据父节点,例:<br/>
     * a,b,c,d</br>
     * <table border="1px" cellspacing="0px">
     * <tr><th>节点</th><th>父节点</th></tr>
     * <tr><td>a</td><td>null</td></tr>
     * <tr><td>b</td><td>a</td></tr>
     * <tr><td>c</td><td>b</td></tr>
     * <tr><td>d</td><td>c</td></tr>
     * </table>
     * 
     * @param path 树的一条路径,是某个事物下的数据记录列表
     * @param parentNode 路径第一个节点的父节点
     * @return 
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月25日,下午9:42:41
     */
    public void addPath(List<T> path, FpTreeNode<T> parentNode) {
        if (path == null || path.size() == 0) {
            return ;
        }
        
        T firstEl = path.get(0);
        if (parentNode != null 
                && helper.nodeCompare(firstEl, parentNode.getNodeVal())) {
            parentNode.increaseCountOne();
            parentNode.addPath(path.subList(1, path.size()), parentNode);
        } else {
            FpTreeNode<T> fnode = new FpTreeNode<T>(1, firstEl, null, null, this.getHelper()); 
            
            FpTreeNode<T> exsistChild = this.findChild(fnode.getNodeVal());
            if (exsistChild != null) {
                exsistChild.increaseCountOne();
                exsistChild.addPath(path.subList(1, path.size()), exsistChild);
            } else {
                FpTreeNode<T> node = this.addChild(fnode);
                node.addPath(path.subList(1, path.size()), node);
            }
        }
    }
    
    /**
     * 描述:计数器加一
     *
     * @return 当前节点计数器
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月23日,下午7:36:21
     */
    public long increaseCountOne() {
        return this.increaseCount(1);
    }
    
    /**
     * 描述:
     *
     * @param increasement
     * @return 当前节点计数器
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月23日,下午7:37:16
     */
    public long increaseCount(long increasement) {
        this.count += increasement;
        return this.count;
    }
    
    /**
     * 描述: 当前节点寻找指定子节点,有,则返回节点,无则返回null
     *
     * @param childVal
     * @return
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月23日,下午7:41:42
     */
    public FpTreeNode<T> findChild(T childVal) {
        if (children == null) {
            return null;
        }
        for (FpTreeNode<T> child : children) {
            if (helper.nodeCompare(child.getNodeVal(), childVal)) {
                return child;
            }
        }
        return null;
    }

    @Override
    public String toString() {
        return super.toString() + "-node (val:" + this.getNodeVal() + ", count: " + this.getCount() + ")";
    }

    public long getCount() {
        return count;
    }

    public void setCount(long count) {
        this.count = count;
    }

    public T getNodeVal() {
        return nodeVal;
    }

    public void setNodeVal(T nodeVal) {
        this.nodeVal = nodeVal;
    }

    public FpTreeNode<T> getParent() {
        return parent;
    }

    public void setParent(FpTreeNode<T> parent) {
        this.parent = parent;
    }

    public List<FpTreeNode<T>> getChildren() {
        return children;
    }

    public void setChildren(List<FpTreeNode<T>> children) {
        this.children = children;
    }

    public FpTreeHelper<T> getHelper() {
        return helper;
    }

    public void setHelper(FpTreeHelper<T> helper) {
        this.helper = helper;
    }
}

FpTreeHeader类

package com.slyk.sdp.algorithms.externalAlgorithms.fpTree;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.slyk.sdp.algorithms.externalAlgorithms.fpTree.util.ListSortUtils;

/**
 * 描述:fptree项头表
 * 
 * @param <K>
 *
 * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
 * @created on 2019年5月23日,下午8:05:14
 */
@SuppressWarnings("hiding")
public class FpTreeHeader<K, Integer> extends LinkedHashMap <K, java.lang.Integer> {
    private static Logger logger = LoggerFactory.getLogger(FpTreeHeader.class);
    
    private static final long serialVersionUID = 1L;
    
    /**
     * 过滤、排序后的原始数据,用以做构建fptree输入数据
     */
    private List<List<K>> inputData = new LinkedList<List<K>>();
    
    /**
     * helper
     */
    private FpTreeHelper<K> helper;
    
    /**
     * 节点链,fptree构建后依据项头表建立的节点链列表
     */
    private Map<K, List<FpTreeNode<K>>> treeNodeMap = new LinkedHashMap<K, List<FpTreeNode<K>>>();
    
    /**
     * 描述:添加helper
     *
     * @param helper
     * @return
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月29日,上午10:54:18
     */
    public FpTreeHeader<K, Integer> addHelper( FpTreeHelper<K> helper) {
        this.setHelper(helper);
        return this;
    }
    
    /**
     * 描述: 构建节点链列表
     *
     * @param node
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * Created On 2019年5月29日, 上午1:13:27
     */
    protected void buildNodeEntryList(FpTreeNode<K> node) {
        if (node.getCount() != -1) {
            List<FpTreeNode<K>> nodeList = treeNodeMap.get(node.getNodeVal());
            if (nodeList == null) {
                nodeList = new ArrayList<FpTreeNode<K>>();
                nodeList.add(node);
                treeNodeMap.put(node.getNodeVal(), nodeList);
            } else {
                nodeList.add(node);
            }
        }
        
        if (node.getChildren() == null) {
            return ;
        }
        
        for (FpTreeNode<K> child : node.getChildren()) {
            buildNodeEntryList(child);
        }
    }
    
    /**
     * 描述:构建项头表
     *
     * @param sourceData
     * @param absSupport
     * @return
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月23日,下午8:36:58
     */
    @SuppressWarnings("unchecked")
    public FpTreeHeader<K, Integer> buildTable(List<List<K>> sourceData, int absSupport) {
        Assert.notNull(this.helper, "helper cannot be null, Set helper first!");
        
        logger.debug("构建项头表.");
        for (List<K> data : sourceData) {
            for (K k : data) {
                if (this.get(k) == null) {
                    this.put(k, 1);
                } else {
                    this.put(k, this.get(k) + 1);
                }
            }
        }
        
        // 过滤不满足项目
        Set<java.util.Map.Entry<K, java.lang.Integer>> set = this.entrySet();
        Iterator<java.util.Map.Entry<K, java.lang.Integer>> ite = set.iterator();
        while (ite.hasNext()) {
            java.util.Map.Entry<K, java.lang.Integer> entry = ite.next();
            if (entry.getValue() < absSupport) {
                ite.remove();
            }
        }
        
        // 项头表排序
        List<K> keylist = new ArrayList<K>(this.keySet());
        Map<K, Integer> thisRef = (Map<K, Integer>) new LinkedHashMap<String, Integer>();
        ListSortUtils.sort(keylist, this.getHelper().nodeEleCompare((FpTreeHeader<K, java.lang.Integer>) this));
        for (K k : keylist) {
            thisRef.put(k, (Integer) this.get(k));
        }
        this.clear();
        this.putAll((Map<? extends K, ? extends java.lang.Integer>) thisRef);
        
        // 对原始输入数据过滤并排序
        for (List<K> data : sourceData) {
            for (Iterator<K> itr = data.iterator(); itr.hasNext(); ) {
                K k = itr.next();
                if (!this.containsKey(k)) {
                    itr.remove();
                }
            }
            FpTreeHeader<K, java.lang.Integer> _this = (FpTreeHeader<K, java.lang.Integer>) this;
            ListSortUtils.sort(data, new Comparator<K>() {
                @Override
                public int compare(K o1, K o2) {
                    int i = _this.get(o2) - _this.get(o1);
                    if (i == 0) {
                        Iterator<java.util.Map.Entry<K, java.lang.Integer>> itr = _this.entrySet().iterator();
                        int index1 = 0;
                        int index2 = 0;
                        for (int a = 0,b = 0; itr.hasNext(); ) {
                            a = a + 1;
                            b = b + 1;
                            java.util.Map.Entry<K, java.lang.Integer> entry = itr.next();
                            if (helper.nodeCompare(entry.getKey(), o1)) {
                                index1 = a;
                            } else if (helper.nodeCompare(entry.getKey(), o2)) {
                                index2 = b;
                            }
                        }
                        i = index1 - index2;
                    }
                    return i;
                }
                
            });
            if (!data.isEmpty()) {
                inputData.add(data);
            }
        }
        sourceData = null;
        logger.debug("构建项头表完成.");
        return this;
    }

    public List<List<K>> getInputData() {
        return inputData;
    }

    public void setInputData(List<List<K>> inputData) {
        this.inputData = inputData;
    }

    public FpTreeHelper<K> getHelper() {
        return helper;
    }

    public void setHelper(FpTreeHelper<K> helper) {
        this.helper = helper;
    }

    public Map<K, List<FpTreeNode<K>>> getTreeNodeMap() {
        return treeNodeMap;
    }

    public void setTreeNodeMap(Map<K, List<FpTreeNode<K>>> treeNodeMap) {
        this.treeNodeMap = treeNodeMap;
    }
}

FpTree类:

package com.slyk.sdp.algorithms.externalAlgorithms.fpTree;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.slyk.sdp.algorithms.externalAlgorithms.fpTree.util.DoubleKeyMap;

/**
 * FPtree
 * 
 * 描述:@param <T>
 *
 * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
 * @created on 2019年6月3日,下午1:34:22
 */
public class FpTree<T> {
    private static Logger logger = LoggerFactory.getLogger(FpTree.class);
    
    /**
     * 项头表
     */
    private FpTreeHeader<T, Integer> fpTreeHeader;
    
    /**
     * helper
     */
    private FpTreeHelper<T> helper;
    
    /**
     * root node
     */
    private FpTreeNode<T> root;
    
    /**
     * 默认频繁度阈值
     */
    protected static final int DEFAULT_ABS_SUPPORT = 0xf;
    
    private int absSupport = DEFAULT_ABS_SUPPORT;
    
    /**
     * 默认置信度
     */
    private static final int DEFAULT_CONFIDENT = 3;
    
    /**
     * 置信度
     */
    private int confident = DEFAULT_CONFIDENT;
    
    /**
     * 描述:挖掘树
     * <br/>代码参考自《机器学习实战》
     *
     * @param outList
     * @param tree
     * @param basePat
     * @return
     * @throws ClassNotFoundException
     * @throws IOException
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月31日,下午5:50:45
     */
    public List<List<T>> fpGrowth(List<List<T>> outList, FpTree<T> tree, List<T> prefix) throws ClassNotFoundException, IOException {
        logger.debug("开始conditionFpTree数据挖掘计算.");
        //
        // 挖掘频繁项集的步骤如下:
        // 1 从FP树提取条件模式基
        // 2 用条件模式基构造FP树
        // 3 重复1和2直到树只包含一个元素
        //
        DoubleKeyMap<T, List<T>, Integer> cpbs = tree.buildPrefixPath();
        
        // 从项头表逆序访问
        ListIterator<Map.Entry<T, Integer>> li =
                new ArrayList<Map.Entry<T, Integer>>(
                        this.fpTreeHeader.entrySet()).listIterator(this.fpTreeHeader.size()); 
        for ( ;li.hasPrevious(); ) {
            Map.Entry<T, Integer> entry = li.previous(); 
            T fpHeaderItem = entry.getKey();
                       
            List<T> newBasePat = new ArrayList<T>(prefix);
            newBasePat.add(fpHeaderItem);
            
            this.getHelper().resultHandler(newBasePat, confident, entry.getValue());
            logger.debug("发现频繁项集:" + newBasePat.toString());
            
            Set<List<T>> set = cpbs.get(fpHeaderItem).keySet();
            Iterator<List<T>> setItr = set.iterator();
            Map<String, List<T>> cpbInputData = new LinkedHashMap<String, List<T>>();
            for ( ; setItr.hasNext(); ) {
                List<T> cpb = setItr.next();
                Integer count = cpbs.get(fpHeaderItem, cpb);
                for (int repeat = 0; repeat < count; repeat++) {
                    if (!cpb.isEmpty()) {
                        cpbInputData.put(cpb.toString() + "-" + repeat, cpb);
                    }
                }
            }
            FpTree<T> cpbTree = new FpTree<T>();
            cpbTree.setHelper(this.getHelper());
            cpbTree = cpbTree.init(this.getAbsSupport(), this.getConfident(), cpbInputData);
            if (!cpbTree.getFpTreeHeader().keySet().isEmpty()) {
                cpbTree.fpGrowth(outList, cpbTree, newBasePat);
            }
            
            cpbTree = null;
            cpbInputData = null;
        }
        logger.debug("完成conditionFpTree数据挖掘计算.");
        return outList;
    }
    
    /**
     * 描述:初始、构建fptree,为数据挖掘做准备
     * <br/>
     * <strong>
     * 输入sourceMap数据结构:</br>
     * KEY&emsp;&emsp;            LIST</br>
     * T0&emsp;&emsp;             1,2,3,4</br>
     * T1&emsp;&emsp;             1</br>
     * T2&emsp;&emsp;             3,4</br>
     * T3&emsp;&emsp;             2,3</br>
     * </strong>
     * 
     * @param absSupport
     * @param sourceMap
     * @return
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月29日,上午11:53:11
     */
    public FpTree<T> init(Integer absSupport, Integer confident, Map<String, List<T>> sourceMap) {
        logger.debug("开始fptree构建.");
        this.absSupport = absSupport == null ? this.getAbsSupport() : absSupport;
        this.confident = confident == null ? this.getConfident() : confident;
        
        List<List<T>> sourceData = new ArrayList<List<T>>();
        Set<String> keys = sourceMap.keySet();
        for (String key : keys) {
            List<T> inList = sourceMap.get(key);
            sourceData.add(inList);
        }
        
        this.fpTreeHeader = new FpTreeHeader<T, Integer>().addHelper(helper)
                .buildTable(sourceData, absSupport);
        sourceData = null;
        
        root = buildTree();
        
//        logger.info("构建构建节点链.");
        this.fpTreeHeader.buildNodeEntryList(root);
//        logger.info("构建构建节点链完成.");
        logger.debug("完成fptree构建..");
        return this;
    } 
    
    /**
     * 描述:构建条件模式基
     *
     * @return
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月29日,下午2:37:47
     */
    public DoubleKeyMap<T, List<T>, Integer> buildPrefixPath() {
        Assert.notNull(this.fpTreeHeader, "fpTreeHeader cannot be null, Set helper first!");
        logger.debug("构建条件模式基");
        DoubleKeyMap<T, List<T>, Integer> cpb = new DoubleKeyMap<T, List<T>, Integer>();
        // 从项头表逆序寻找条件模式集
        ListIterator<Map.Entry<T, Integer>> li =
                new ArrayList<Map.Entry<T, Integer>>(
                        this.fpTreeHeader.entrySet()).listIterator(this.fpTreeHeader.size()); 
        for ( ;li.hasPrevious(); ) {
            Map.Entry<T, Integer> entry = li.previous(); 
            T fpHeaderItem = entry.getKey();
            List<FpTreeNode<T>> nodeList = this.getFpTreeHeader().getTreeNodeMap().get(fpHeaderItem);
            for (FpTreeNode<T> node : nodeList) {
                cpb = findPrefixPath(node, cpb);
            }
        }
        logger.debug("完成构建条件模式基");
        return cpb;
    }
    
    /**
     * 描述:寻找条件模式基
     *
     * @param node 节点链中的节点
     * @return
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月27日,上午1:05:45
     */
    private DoubleKeyMap<T, List<T>, Integer> findPrefixPath(FpTreeNode<T> node, DoubleKeyMap<T, List<T>, Integer> cpb) {
        Assert.notNull(this.fpTreeHeader, "fpTreeHeader cannot be null, Set helper first!");
        List<T> prefixPath = new ArrayList<T>();
        FpTreeNode<T> up = node.getParent();
        while (up.getParent() != null) {
            prefixPath.add(up.getNodeVal());
            up = up.getParent();
        }
        Collections.reverse(prefixPath);
        cpb.put(node.getNodeVal(), prefixPath, (int) node.getCount());
        return cpb;
    }
    
    /**
     * 描述:构建fptree
     *
     * @return
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月24日,上午11:45:34
     */
    private FpTreeNode<T> buildTree() {
        Assert.notNull(this.helper, "helpser cannot be null, Set helper first!");
        Assert.notNull(this.fpTreeHeader, "fpTreeHeader cannot be null, Set helper first!");
        
        FpTreeNode<T> rootNode = new FpTreeNode<T>(-1, null, null, null, helper);
        
        int index = 0;
        for (List<T> path : this.fpTreeHeader.getInputData()) {
            rootNode.addPath(path, rootNode);
            index += 1;
            logger.debug("fptree完成进度:" + index + "/" + this.fpTreeHeader.getInputData().size());
        }
        
        return rootNode;
    }
    
    /**
     * 描述: 打印树,以便直观观察
     *
     * @param node
     * @param ins
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * Created On 2019年5月29日, 上午12:27:43
     */
    public void display(FpTreeNode<T> node, int ins) {
        if (node.getParent() == null) {
            logger.info("打印树形结构如下:");
        }
        System.out.print(StringUtils.repeat("  ", ins) + node.getNodeVal() + "  " + node.getCount() + "\n");
        if (node.getChildren() == null) {
            return ;
        }
        ins = ins + 1;
        for (FpTreeNode<T> subNode : node.getChildren()) {
            display(subNode, ins);
        }
    }
    
    /**
     * 描述:deepCopy
     *
     * @param src
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月30日,下午5:28:26
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {  
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();  
        ObjectOutputStream out = new ObjectOutputStream(byteOut);  
        out.writeObject(src); 
        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  
        ObjectInputStream in = new ObjectInputStream(byteIn);  
        List<T> dest = (List<T>) in.readObject();  
        return dest;  
    }  

    public FpTreeHeader<T, Integer> getFpTreeHeader() {
        return fpTreeHeader;
    }

    public void setFpTreeHeader(FpTreeHeader<T, Integer> fpTreeHeader) {
        this.fpTreeHeader = fpTreeHeader;
    }

    public FpTreeHelper<T> getHelper() {
        return helper;
    }

    public void setHelper(FpTreeHelper<T> helper) {
        this.helper = helper;
    }

    public FpTreeNode<T> getRoot() {
        return root;
    }

    public void setRoot(FpTreeNode<T> root) {
        this.root = root;
    }

    public int getAbsSupport() {
        return absSupport;
    }

    public void setAbsSupport(int absSupport) {
        this.absSupport = absSupport;
    }

    public int getConfident() {
        return confident;
    }

    public void setConfident(int confident) {
        this.confident = confident;
    }
}

FpTreeHelper类

package com.slyk.sdp.algorithms.externalAlgorithms.fpTree;

import java.util.Comparator;
import java.util.List;

/**
 * 描述:fptree helper class
 * 
 * @param <T>
 *
 * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
 * @created on 2019年5月23日,下午7:49:46
 */
public interface FpTreeHelper<T> {
    /**
     * 描述:比较目标节点和源节点是否相等,等返回true,否则false
     *
     * @param target
     * @param source
     * @return
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月23日,下午7:52:35
     */
    boolean nodeCompare(T target, T source);
    
    /**
     * 描述:比较节点内容
     *
     * @return
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年5月29日,上午10:42:35
     */
    Comparator<T> nodeEleCompare(FpTreeHeader<T, Integer> header);
    
    /**
     * 描述: 找到的结果处理
     *
     * @param result 单条记录
     * @param extArgs 附加参数
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * Created On 2019年6月2日, 上午1:36:35
     */
    void resultHandler(List<T> result, Object ...extArgs);
}

DoubleKeyMap类

package com.slyk.sdp.algorithms.externalAlgorithms.fpTree.util;

import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public class DoubleKeyMap<Key1, Key2, Value> {
    Map<Key1, Map<Key2, Value>> data = new LinkedHashMap<Key1, Map<Key2, Value>>();

    public Value put(Key1 k1, Key2 k2, Value v) {
        Map<Key2, Value> data2 = data.get(k1);
        Value prev = null;
        if ( data2==null ) {
            data2 = new LinkedHashMap<Key2, Value>();
            data.put(k1, data2);
        }
        else {
            prev = data2.get(k2);
        }
        data2.put(k2, v);
        return prev;
    }

    public Value get(Key1 k1, Key2 k2) {
        Map<Key2, Value> data2 = data.get(k1);
        if ( data2==null ) return null;
        return data2.get(k2);
    }

    public Map<Key2, Value> get(Key1 k1) { return data.get(k1); }

    /** Get all values associated with primary key */
    public Collection<Value> values(Key1 k1) {
        Map<Key2, Value> data2 = data.get(k1);
        if ( data2==null ) return null;
        return data2.values();
    }

    /** get all primary keys */
    public Set<Key1> keySet() {
        return data.keySet();
    }

    /** get all secondary keys associated with a primary key */
    public Set<Key2> keySet(Key1 k1) {
        Map<Key2, Value> data2 = data.get(k1);
        if ( data2==null ) return null;
        return data2.keySet();
    }

    public Collection<Value> values() {
        Set<Value> s = new HashSet<Value>();
        for (Map<Key2, Value> k2 : data.values()) {
            for (Value v : k2.values()) {
                s.add(v);
            }
        }
        return s;
    }
    
    @SuppressWarnings("unchecked")
    public void print() {
        System.out.println("条件模式基集合:");
        Set<Key1> kset = this.keySet();
        for (Iterator<Key1> itrKey1 = kset.iterator(); itrKey1.hasNext();) {
            Key1 key1 = itrKey1.next();
            for (Iterator<Key2> itrKey2 = this.get(key1).keySet().iterator(); itrKey2.hasNext();) {
                Object key2 = itrKey2.next();
                System.out.println(key1 + ":" + key2 + "(" + this.get(key1, (Key2) key2) + ")");
            }
        }
    }
}

ListSortUtils类

package com.slyk.sdp.algorithms.externalAlgorithms.fpTree.util;

import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;

/**
 * 描述: 求集合排序,原本集合collections包有排序功能,但是jdk7后改为 timsort排序实现,此类实现存在问题,例如: int[]
 * sample = new int[]
 * {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 * ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-2,1,0,-2,0,0,0,0};
 * 如上例子数据在timsort排序将会报错,因此排序算法将参考JDK5的LegacyMergeSort算法封装排序。
 *
 * @author <a href=‘mailto:xiaomingyang@aksl.com.cn‘>xiaomingyang</a>
 *         2019年6月2日,下午11:35:16
 * @version v0.1
 */
public class ListSortUtils {
    /**
     * 描述:参考Collections.sort()方法
     *
     * @param list
     * @param c
     * @author <a href=‘mailto:xiaomingyang@shulianyikang.com‘>xiaomingyang</a>
     * @created on 2019年6月3日,下午1:35:04
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static <T> void sort(List<T> list, Comparator<? super T> c) {
        Object[] a = list.toArray();
        sort(a, (Comparator) c);
        ListIterator i = list.listIterator();
        for (int j = 0; j < a.length; j++) {
            i.next();
            i.set(a[j]);
        }
    }

    public static <T> void sort(T[] a, Comparator<? super T> c) {
        T[] aux = (T[]) a.clone();
        if (c == null)
            mergeSort(aux, a, 0, a.length, 0);
        else
            mergeSort(aux, a, 0, a.length, 0, c);
    }

    private static final int INSERTIONSORT_THRESHOLD = 7;

    private static void swap(Object[] x, int a, int b) {
        Object t = x[a];
        x[a] = x[b];
        x[b] = t;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static void mergeSort(Object[] src, Object[] dest, int low,
            int high, int off) {
        int length = high - low;

        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i = low; i < high; i++)
                for (int j = i; j > low
                        && ((Comparable) dest[j - 1]).compareTo(dest[j]) > 0; j--)
                    swap(dest, j, j - 1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow = low;
        int destHigh = high;
        low += off;
        high += off;
        int mid = (low + high) >> 1;
        mergeSort(dest, src, low, mid, -off);
        mergeSort(dest, src, mid, high, -off);

        // If list is already sorted, just copy from src to dest. This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (((Comparable) src[mid - 1]).compareTo(src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        // Merge sorted halves (now in src) into dest
        for (int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid
                    && ((Comparable) src[p]).compareTo(src[q]) <= 0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static void mergeSort(Object[] src, Object[] dest, int low,
            int high, int off, Comparator c) {
        int length = high - low;

        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i = low; i < high; i++)
                for (int j = i; j > low && c.compare(dest[j - 1], dest[j]) > 0; j--)
                    swap(dest, j, j - 1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow = low;
        int destHigh = high;
        low += off;
        high += off;
        int mid = (low + high) >> 1;
        mergeSort(dest, src, low, mid, -off, c);
        mergeSort(dest, src, mid, high, -off, c);

        // If list is already sorted, just copy from src to dest. This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (c.compare(src[mid - 1], src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        // Merge sorted halves (now in src) into dest
        for (int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }
}

App类

package com.slyk.sdp.algorithms;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.slyk.sdp.algorithms.externalAlgorithms.fpTree.FpTree;
import com.slyk.sdp.algorithms.externalAlgorithms.fpTree.FpTreeHeader;
import com.slyk.sdp.algorithms.externalAlgorithms.fpTree.FpTreeHelper;

/**
 * Hello world!
 *
 */
public class App {
    private BufferedReader br;

    private static int frequency = 2;
    
    private static int confident = 3;

    public void getSourceData() throws IOException {
        Map<String, List<String>> inputMap = ReadFile();
        System.out.println(inputMap);
    }

    private Map<String, List<String>> ReadFile() throws IOException {
        Map<String, List<String>> inputMap = new LinkedHashMap<String, List<String>>();
        br = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("/input.csv")));
        String line = null;
        int lineNum = 0;
        while (null != (line = br.readLine())) {
            // System.out.println("T" + lineNum + ":" + line);
            lineNum += 1;
            List<String> list = Arrays.asList(line.split(","));
            inputMap.put("T" + lineNum, new ArrayList<String>(list));
        }
        return inputMap;
    }
    
    public void fpGrowth() throws IOException, ClassNotFoundException {
        List<List<String>> resultList = new ArrayList<List<String>>();
        Map<String, List<String>> inputMap = ReadFile();
        FpTree<String> tree = new FpTree<String>();
        tree.setHelper(new FpTreeHelper<String>() {
            private Comparator<String> comparetor = null;
            
            private File resultFile = new File("./result.txt");
            
            private BufferedWriter writer = null;
            
            private FileOutputStream fos = null;
            
            @Override
            public boolean nodeCompare(String target, String source) {
                return StringUtils.equals(target, source);
            }

            /**
             * 节点内容需要按项头表统计数量逆序排序
             */
            @Override
            public Comparator<String> nodeEleCompare(FpTreeHeader<String, Integer> header) {
                if (comparetor == null) {
                    comparetor = new Comparator<String>() {
                        @Override
                        public int compare(String o1, String o2) {
                            int i = header.get(o2) - header.get(o1);
                            return i;
                        }  
                    };
                }
                return comparetor;
            }

            @Override
            public void resultHandler(List<String> result, Object ...extArgs) {
                try {
                    if (result.size() < (int) extArgs[0]) {
                        return ;
                    }
                    resultList.add(result);
                    fos = new FileOutputStream(resultFile, true);
                    writer = new BufferedWriter(new OutputStreamWriter(fos));
                    writer.write(result.toString() + "   " + (int)extArgs[1] + "\r\n");
                    writer.flush();
                    fos.flush();
                    writer.close();
                    fos.close();
                    System.out.println(result);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        
        tree.fpGrowth(new ArrayList<List<String>>(), 
                tree.init(2, 2, inputMap), new ArrayList<String>());
        tree.display(tree.getRoot(), 2);
        System.out.println("===========================");
        for (Object o : resultList) {
            System.out.println(o);
        }
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        App app = new App();
        app.fpGrowth();
    }
}

运行结果:

[4e953a9700fc3a4de58eb3b066eb4c74, 6d7e042a000deca140c330ab99896ebd]
[4e953a9700fc3a4de58eb3b066eb4c74, 6d7e042a000deca140c330ab99896ebd, 6f9ef114e4478a961bf3e59d6441f243]
[4e953a9700fc3a4de58eb3b066eb4c74, 40b0229cbf83c8857e8c9e7d79bec8e9]
[4e953a9700fc3a4de58eb3b066eb4c74, 40b0229cbf83c8857e8c9e7d79bec8e9, a0a5dff287d5f43498a81934df34f6e1]
[4e953a9700fc3a4de58eb3b066eb4c74, 40b0229cbf83c8857e8c9e7d79bec8e9, a0a5dff287d5f43498a81934df34f6e1, 6f9ef114e4478a961bf3e59d6441f243]
[4e953a9700fc3a4de58eb3b066eb4c74, 40b0229cbf83c8857e8c9e7d79bec8e9, 6f9ef114e4478a961bf3e59d6441f243]
[4e953a9700fc3a4de58eb3b066eb4c74, a0a5dff287d5f43498a81934df34f6e1]
[4e953a9700fc3a4de58eb3b066eb4c74, a0a5dff287d5f43498a81934df34f6e1, 6f9ef114e4478a961bf3e59d6441f243]
[4e953a9700fc3a4de58eb3b066eb4c74, 6f9ef114e4478a961bf3e59d6441f243]
[157d68a0e73262e443ad843e7d29195f, 4f312b0f37bf9d86333114a4f467ddc3]
[6d7e042a000deca140c330ab99896ebd, 6f9ef114e4478a961bf3e59d6441f243]
[60dec45d8b4bbda8681e85f05e979f95, 4b041b8fab2bd834e6acc34a541520cb]
[dd416340a4613c46ed12b87717e4a8ac, 40b0229cbf83c8857e8c9e7d79bec8e9]
[dd416340a4613c46ed12b87717e4a8ac, 40b0229cbf83c8857e8c9e7d79bec8e9, a0a5dff287d5f43498a81934df34f6e1]
[dd416340a4613c46ed12b87717e4a8ac, a0a5dff287d5f43498a81934df34f6e1]
[40b0229cbf83c8857e8c9e7d79bec8e9, a0a5dff287d5f43498a81934df34f6e1]
[40b0229cbf83c8857e8c9e7d79bec8e9, 6f9ef114e4478a961bf3e59d6441f243]
[40b0229cbf83c8857e8c9e7d79bec8e9, 6f9ef114e4478a961bf3e59d6441f243, a0a5dff287d5f43498a81934df34f6e1]
[a0a5dff287d5f43498a81934df34f6e1, 6f9ef114e4478a961bf3e59d6441f243]

 

注意的问题:

  1. jdk7以上在做排序时候不要用Collection工具自带的排序,有坑滴;
  2. 关于fptree树,节点顺序并不会影响结果;
  3. 关于频繁项挖掘过程中,可能会出现很多频繁项集,所以在计算过程中注意内存问题,当然,解决办法就是在resultHandler方法中进行频繁项集的结果合并,参数将会传入频繁度,所以result中的数据可以和已有结果进行比较,如果result+频繁度已经在resultList中存在,则不处理此结果,如果resultList中的结果被包含与result中,更新resultList对应项,这样只保持最大结果集,舍弃中间结果来节省内存,同时对result应该做deepCopy,不然GC时释放不掉引用,内存会溢出;
  4. 《机器学习实战》中的代码有错,下面的是修改过的;
  5. 对于上亿上十亿的输入数据,速度提升办法是把数据切成几个片,每个片都跑fp-growth,跑完所有结果汇集起来继续切片,再跑,反复这个过程直到输入数据和输出数据一样就终止;

对于结果正确性的验证采用《机器学习实战》一书中的代码来验证

‘‘‘
Created on Jun 14, 2011
FP-Growth FP means frequent pattern
the FP-Growth algorithm needs: 
1. FP-tree (class treeNode)
2. header table (use dict)

This finds frequent itemsets similar to apriori but does not 
find association rules.  

@author: Peter
‘‘‘
class treeNode:
    def __init__(self, nameValue, numOccur, parentNode):
        self.name = nameValue
        self.count = numOccur
        self.nodeLink = None
        self.parent = parentNode      #needs to be updated
        self.children = {} 
    
    def inc(self, numOccur):
        self.count += numOccur
        
    def disp(self, ind=1):
        print   *ind, self.name,  , self.count
        for child in self.children.values():
            child.disp(ind+1)

def createTree(dataSet, minSup=1): #create FP-tree from dataset but don‘t mine
    headerTable = {}
    #go over dataSet twice
    for trans in dataSet:#first pass counts frequency of occurance
        for item in trans:
            headerTable[item] = headerTable.get(item, 0) + dataSet[trans]
    for k in headerTable.keys():  #remove items not meeting minSup
        if headerTable[k] < minSup: 
            del(headerTable[k])
    freqItemSet = set(headerTable.keys())
    #print ‘freqItemSet: ‘,freqItemSet
    if len(freqItemSet) == 0: return None, None  #if no items meet min support -->get out
    for k in headerTable:
        headerTable[k] = [headerTable[k], None] #reformat headerTable to use Node link 
    #print ‘headerTable: ‘,headerTable
    retTree = treeNode(Null Set, 1, None) #create tree
    for tranSet, count in dataSet.items():  #go through dataset 2nd time
        localD = {}
        for item in tranSet:  #put transaction items in order
            if item in freqItemSet:
                localD[item] = headerTable[item][0]
        if len(localD) > 0:
            orderedItems = [v[0] for v in sorted(localD.items(), key=lambda p: p[1], reverse=True)]
            updateTree(orderedItems, retTree, headerTable, count)#populate tree with ordered freq itemset
    return retTree, headerTable #return tree and header table

def updateTree(items, inTree, headerTable, count):
    if items[0] in inTree.children:#check if orderedItems[0] in retTree.children
        inTree.children[items[0]].inc(count) #incrament count
    else:   #add items[0] to inTree.children
        inTree.children[items[0]] = treeNode(items[0], count, inTree)
        if headerTable[items[0]][1] == None: #update header table 
            headerTable[items[0]][1] = inTree.children[items[0]]
        else:
            updateHeader(headerTable[items[0]][1], inTree.children[items[0]])
    if len(items) > 1:#call updateTree() with remaining ordered items
        updateTree(items[1::], inTree.children[items[0]], headerTable, count)
        
def updateHeader(nodeToTest, targetNode):   #this version does not use recursion
    while (nodeToTest.nodeLink != None):    #Do not use recursion to traverse a linked list!
        nodeToTest = nodeToTest.nodeLink
    nodeToTest.nodeLink = targetNode
        
def ascendTree(leafNode, prefixPath): #ascends from leaf node to root
    if leafNode.parent != None:
        prefixPath.append(leafNode.name)
        ascendTree(leafNode.parent, prefixPath)
    
def findPrefixPath(basePat, treeNode): #treeNode comes from header table
    condPats = {}
    while treeNode != None:
        prefixPath = []
        ascendTree(treeNode, prefixPath)
        if len(prefixPath) > 1: 
            condPats[frozenset(prefixPath[1:])] = treeNode.count
        treeNode = treeNode.nodeLink
    return condPats

def mineTree(inTree, headerTable, minSup, preFix, freqItemList):
    bigL = [v[0] for v in sorted(headerTable.items(), key=lambda p: p[1])]#(sort header table)
    for basePat in bigL:  #start from bottom of header table
        newFreqSet = preFix.copy()
        newFreqSet.add(basePat)
        #print ‘finalFrequent Item: ‘,newFreqSet    #append to set
        freqItemList.append(newFreqSet)
        condPattBases = findPrefixPath(basePat, headerTable[basePat][1])
        #print ‘condPattBases :‘,basePat, condPattBases
        #2. construct cond FP-tree from cond. pattern base
        myCondTree, myHead = createTree(condPattBases, minSup)
        #print ‘head from conditional tree: ‘, myHead
        if myHead != None: #3. mine cond. FP-tree
            #print ‘conditional tree for: ‘,newFreqSet
            #myCondTree.disp(1)            
            mineTree(myCondTree, myHead, minSup, newFreqSet, freqItemList)

def loadSimpDat():
    simpDat = [[r, z, h, j, p],
               [z, y, x, w, v, u, t, s],
               [z],
               [r, x, n, o, s],
               [y, r, x, z, q, t, p],
               [y, z, x, e, q, s, t, m]]
    return simpDat

def createInitSet(dataSet):
    retDict = {}
    for trans in dataSet:
        # retDict[frozenset(trans)] = 1
        retDict[frozenset(trans)] = retDict.get(frozenset(trans), 0) + 1
    return retDict

import twitter
from time import sleep
import re

def textParse(bigString):
    urlsRemoved = re.sub((http:[/][/]|www.)([a-z]|[A-Z]|[0-9]|[/.]|[~])*, ‘‘, bigString)    
    listOfTokens = re.split(r\W*, urlsRemoved)
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]

def getLotsOfTweets(searchStr):
    CONSUMER_KEY = ‘‘
    CONSUMER_SECRET = ‘‘
    ACCESS_TOKEN_KEY = ‘‘
    ACCESS_TOKEN_SECRET = ‘‘
    api = twitter.Api(consumer_key=CONSUMER_KEY, consumer_secret=CONSUMER_SECRET,
                      access_token_key=ACCESS_TOKEN_KEY, 
                      access_token_secret=ACCESS_TOKEN_SECRET)
    #you can get 1500 results 15 pages * 100 per page
    resultsPages = []
    for i in range(1,15):
        print "fetching page %d" % i
        searchResults = api.GetSearch(searchStr, per_page=100, page=i)
        resultsPages.append(searchResults)
        sleep(6)
    return resultsPages

def mineTweets(tweetArr, minSup=5):
    parsedList = []
    for i in range(14):
        for j in range(100):
            parsedList.append(textParse(tweetArr[i][j].text))
    initSet = createInitSet(parsedList)
    myFPtree, myHeaderTab = createTree(initSet, minSup)
    myFreqList = []
    mineTree(myFPtree, myHeaderTab, minSup, set([]), myFreqList)
    return myFreqList

simpDat = []
for line in open(/home/xxxxxxx/yyyyyy/input.csv, r):
    simpDat.append(line.replace("\n", "").split(","))

minSup = 2
initSet = createInitSet(simpDat)
myFPtree, myHeaderTab = createTree(initSet, minSup)
myFreqList = []
mineTree(myFPtree, myHeaderTab, minSup, set([]), myFreqList)
for i in myFreqList:
    if len(i) < 2:
        continue
    print i

print ============================
myFPtree.disp()
#############################333
#minSup = 3
#simpDat = loadSimpDat()
#initSet = createInitSet(simpDat)
#myFPtree, myHeaderTab = createTree(initSet, minSup)
#myFPtree.disp()
#myFreqList = []
#mineTree(myFPtree, myHeaderTab, minSup, set([]), myFreqList)
#for i in myFreqList:
#    print i

结果:

set([‘157d68a0e73262e443ad843e7d29195f‘, ‘4f312b0f37bf9d86333114a4f467ddc3‘])
set([‘6f9ef114e4478a961bf3e59d6441f243‘, ‘40b0229cbf83c8857e8c9e7d79bec8e9‘])
set([‘a0a5dff287d5f43498a81934df34f6e1‘, ‘6f9ef114e4478a961bf3e59d6441f243‘, ‘40b0229cbf83c8857e8c9e7d79bec8e9‘])
set([‘a0a5dff287d5f43498a81934df34f6e1‘, ‘40b0229cbf83c8857e8c9e7d79bec8e9‘])
set([‘a0a5dff287d5f43498a81934df34f6e1‘, ‘dd416340a4613c46ed12b87717e4a8ac‘])
set([‘40b0229cbf83c8857e8c9e7d79bec8e9‘, ‘dd416340a4613c46ed12b87717e4a8ac‘])
set([‘a0a5dff287d5f43498a81934df34f6e1‘, ‘40b0229cbf83c8857e8c9e7d79bec8e9‘, ‘dd416340a4613c46ed12b87717e4a8ac‘])
set([‘a0a5dff287d5f43498a81934df34f6e1‘, ‘4e953a9700fc3a4de58eb3b066eb4c74‘])
set([‘a0a5dff287d5f43498a81934df34f6e1‘, ‘6f9ef114e4478a961bf3e59d6441f243‘, ‘4e953a9700fc3a4de58eb3b066eb4c74‘])
set([‘4e953a9700fc3a4de58eb3b066eb4c74‘, ‘40b0229cbf83c8857e8c9e7d79bec8e9‘])
set([‘a0a5dff287d5f43498a81934df34f6e1‘, ‘4e953a9700fc3a4de58eb3b066eb4c74‘, ‘40b0229cbf83c8857e8c9e7d79bec8e9‘])
set([‘6f9ef114e4478a961bf3e59d6441f243‘, ‘4e953a9700fc3a4de58eb3b066eb4c74‘, ‘40b0229cbf83c8857e8c9e7d79bec8e9‘])
set([‘a0a5dff287d5f43498a81934df34f6e1‘, ‘6f9ef114e4478a961bf3e59d6441f243‘, ‘4e953a9700fc3a4de58eb3b066eb4c74‘, ‘40b0229cbf83c8857e8c9e7d79bec8e9‘])
set([‘6f9ef114e4478a961bf3e59d6441f243‘, ‘4e953a9700fc3a4de58eb3b066eb4c74‘])
set([‘60dec45d8b4bbda8681e85f05e979f95‘, ‘4b041b8fab2bd834e6acc34a541520cb‘])
set([‘6f9ef114e4478a961bf3e59d6441f243‘, ‘6d7e042a000deca140c330ab99896ebd‘])
set([‘4e953a9700fc3a4de58eb3b066eb4c74‘, ‘6d7e042a000deca140c330ab99896ebd‘])
set([‘6f9ef114e4478a961bf3e59d6441f243‘, ‘4e953a9700fc3a4de58eb3b066eb4c74‘, ‘6d7e042a000deca140c330ab99896ebd‘])
set([‘a0a5dff287d5f43498a81934df34f6e1‘, ‘6f9ef114e4478a961bf3e59d6441f243‘])

两者结果完全一致。

input.csv

00ec5bcf5cdf6ac416e600b2bef9a7c5
e46289d37fa76918074ed8119f65a5f2
507362674ccf915721cfc5d80027956d
65e7c40d57dac350a511664678177df9
1952a815e289a25396905fbe8f29f671
b881f5f8dc378d3049d1b9720e10e063
4db883d0d82be0f97e533f25e5dd1363
fe90159c19ea82a30c75f42b5fe25fc1
30fd9647914621e222105852429b2191
963c824e0b07a3f98f301e3e7cd442ee
bb7c0faa9029b682b32e0997f3cc7b70
65066e0d171be18d92f1e601aaa36260
d63fbd5f0d6ac07328e33358cb058a88
0d9d6fa94ae5216d9bcb9052f50f96cb
4968949809058c41ca58ea531792dafb
3626a5b24d53f51320b211356d251f8e
5bec040b123435df0d1806ddb50cbe9f
6133600a0f61d01e5a6fec07a5ae09aa
5a014e82fe823aebc64152c65ac86a46
fe90159c19ea82a30c75f42b5fe25fc1
dc9182ae415b862068cc47750965de96
13bd89481a54c506f4f16cfe1e139d25
793acae5d364d1ed2156f56b7702ded9
381d2f41181f2158b793fc546e9a4a2b
f84846d7ac6bc61b326ad880cbf28acf
ca954af7a2442530914fcfa720c724fe
01a9d2cfbdc7b65a4f9e56ac9842c2b1
4db301bedeefd96771160df867da5044
289b8b2fdc152c17d589997c58aa3d98
14850b4cd1651f79eb5235000391da47
4e8ea8316ec0888726c2a43d5337da63
16f289b12124693df4f5177fb8bcadef
ef280f9608bfc2c73cc1f238db25060a
635572e7b99059adc55910638d6aba95
a9b822be6e43936173779e3641cccf37
6394940445dd407a39da9df310337b7d
731481a51f92ca1165fd56cc07a85bb9
682268b74cf72bef28b3a2b697524f64
8432e000ce9d8fc9acf382803950677f
70e566a092167f5ee4fdccaea4af6252
fe640b2dd98e4b1ab800169645b5562a
4e08f2f6c64e001b5f6095a38982ebc1
bc154087659431c11af968bbc165f79e,4d3cdd247fca8f3aacf2d50ea19faab2
c92f34dc31db156f4cd691feb313a19f
265152567ab5b818adf0ce68801b8fa2
ae5c3471f12387be2adebc7922067ff0
021c070c1f6250468fa9caf0eae5c2ff
cbd465702d40fa7da1cbf835d7530029
8a2c67da95795be7b01b0ea588f19c51
c5d0e8298c8231faacf37c39d418d250
8b8698cc1746ad3920c7589debfd21de
29e5faf44e37519ab55b95e5b4b87d21
3ca114ffea4bad23501640afaa30013c
2ee79dd0bc121f0704f972c744643feb
c521a7d8077f759012c14c6bfb531cbb
f16a381e577c5ea74b5e2c02a6e64a58
8f7723a6462f1ed308efc9010d02f279
507b57e6d8e48d9df805e58817034fd1
bc85909fa786f72bb236a56a8f17acd6
8b1d9486c7ab2722dfa7cf855cc6e54e
23663f672b0eb30d9400e8009c053e5f
f35b403a015f03b9f4a7abad0ba7c291
6e280b80646b36652853802041e84447
f44422bd25e349884ea5b151708d4168
27551bc092712a80a1dd95cc4715f910
df81af52d06780671644c62b3545e350
39cddf666d46468a97a2029a87461764
e6cd0120d57e5060021ce8abd17edec9
acaa67e0837a1c506b4ee33778c3d34d
686d923dcaddb8bc472129cea202ece5
b26b42fa48cc68886ca0018d9893fcb5
269735d3c130ac7f21444a8f16977d9b
734df183f70f56af8c738f1f51b2d2b0
c3bde1bd54b7318ec7fd8ba0a5ef2799
7cc6000de2268586c1221ee6a1efee37
4d78c3506e84b7ba8a15ef5dd8b1f245
e6cd0120d57e5060021ce8abd17edec9
3e501264d29157bec119ecbeeb24de4c
7b4b0209baeb1fed155051b6f8dbfc58
27551bc092712a80a1dd95cc4715f910
a2469be912c6cb69aecde7af497c5524,6f9ef114e4478a961bf3e59d6441f243
ece4979927cb7d661e2ce393d9084bf1
6a04ee45b8f4727ee9b5bcee145edfa1
276b9794c8a5beeb829cf3a24c4d4c33
f107e3729809537344a0a4531faed727
ece4979927cb7d661e2ce393d9084bf1
3e501264d29157bec119ecbeeb24de4c
4f31add4cfefcf37ff18121282aa9b7b
15a89725f831a8cd0e0594c82f2afc91
bded82f85592223993fa54de9d509fae
3da304722fa16d03f50a47000f7ae920
96e897157907bb08a6d2fbde5a26c51a
0343638604d391dff92e0c9fcfc9cb81
019d0e5eef638d61ba480f6e3d58d003
f75d36e5fcaaddcfeff0e05a2cf15f1d
84924384c3bbec5b6d66f549cc7c9246
3f06d1ef6780bb1a6f4c52417dbe8d0e
60c7819938d980c38e8cea68a6049afa
e68f2f8b35cc47352ce750bdc5f40504
07fc67e89397ab658cde9e3dc4c5640e
b995567c39f8f378112456f0b1594c86
3cc0ee6a7988bba6286796ca0e6630ed
45e0b783d65278cfe5de24ef1e3a8e5a
527cf752f6a0030b3347f0a02f9c8ba8
a93e88e0cd314c1ed59649b720f9c411
2478beac944acaad42aa81cea341e99c
d7ddb097e2138e1c72563b6ccb2af019
b3a19fd58ad492f377431c4000e947b1
ebefb82e4d8e381f2cb9a635b45dd9af
430d475b8859a9d82728b9dadb553fef
542bfb8262044fbb1bb33ce9d3793080
4e08f2f6c64e001b5f6095a38982ebc1
16a826f6cced50d0e3f1aebafeaabf8c
8ce3da76b891f7eb52305c2103a32ee6
1b9d847e265df28ae80d2c4b3a8b2901
d92a2254790d518b031c99fb3b947641
11858f55795ea2ddf27da80247d8793d
45d6388b4664c0bcf33aa878b230998c
dd797073a916722a1fa66a681b5988be
f6951cefbe653efb7a0fcf3ae0885d11
5cd3ceb7c0ef7b92a7c07f1205565d55
b881f5f8dc378d3049d1b9720e10e063
d967e2a9d2e8cdfa87e7f635136f8112
154392ec995e88a7fc95e4cce6af9fb2
2acd298ef2c554aa58ea72759ffb5531
e68f2f8b35cc47352ce750bdc5f40504
eeb94f7eb6bace26301d5aa1ebcab163
5e793aac5bf49d8e56924c19e00e659e
6759e65c8ea397c3fda1a40313b00ff8
311cf3a64ca7218c6c6eb7e9bdd18782
f34424d3f47c5f6d60e146589e3e7e20
3897bfee9eaea606217f4b78e80d18cd
29ad4e576559450a1e82bcd0b8500d28
54497a230f6a4fc29eda3e81a537ac11
4bfaa99566f1f39a2986e859562f18c1
984809425e10ef00c06559d5faba96c1
06efd45528199414f37602fc26b1e5a2
7c960ceb395435846ac66ea3086c970d
1ac1818c94bdcbfbefc0f582a0b25136
391c2ea7ba645d4107db89ac008ad908
2a2459a08478798ff691292ae5b3ca24
1ac1818c94bdcbfbefc0f582a0b25136
0038f2c6b857ba9e169bc6e31a37e86a
0c444905ab9af6e79e7e25ba218eed36
93ebd7da27d17b67cc9a82404a0765d2
cb7d46f2edbb05fdc2d46c12e6167714
911d574eedc431afdce205b6a5a0095a
279d1f9de9e50356e48457ae34e25e27
c9d44105b828c6f72ec5db6d47b8b7b3
7470b8a980304ad11e96195881a5625c
963c824e0b07a3f98f301e3e7cd442ee
e6ce399afaea9e9f7ef02c6ddfa1855f
ccf99ee92991020228083dd81fa4e550
ed648db5c82e86772c1c3f76fb2c42e2
380cea06f23efbb3f9fcd735cb7656e1
edcb078fc1456b07dfdc1cf90c44e3e1
3ddb4ca350c1eb1992bace409bb50396
2a2459a08478798ff691292ae5b3ca24
30fd9647914621e222105852429b2191
37b95887f746d30625bd38d8a1589c7e
efe3b79b8dfbc5534a37c67fd08e3fe0
a93e88e0cd314c1ed59649b720f9c411
06ff223a4e272c58920df2ac32142a5e
bf93f3cce7b449c9fe5cd623d3d99858
ebc1d84a9f5f8e64b19c3d9c11c3fb8d
bad451268583315c8689ea4e737b6c26
c942b22440dfbbf083726d8b843ab2bb
3cc0ee6a7988bba6286796ca0e6630ed
7543b283afa6490c3fd2e572d50dac37
490f654e05b4b26c5c78176d11230540
001b26b67eadea666cc3a9275c676c32
35ce84e828c308566b763a7a21450245
d2e9271fd4a4a1a79a9cbbeee4f4a5e1
b51aec0cfcf0eecbaf583f913cc18f3b
381d2f41181f2158b793fc546e9a4a2b
35440f661f1ad24b3bc9ccd845ab1036
b881f5f8dc378d3049d1b9720e10e063
84924384c3bbec5b6d66f549cc7c9246
cbd465702d40fa7da1cbf835d7530029
baca875e1c185711a26e02177ae10a5d
4a221a726ab64fe169ba2b2a4603b361
16a826f6cced50d0e3f1aebafeaabf8c
119c970e7ad443c12043caa63b6fe7dc
b57508a80ba85a740080aa172b5d60b1
0c444905ab9af6e79e7e25ba218eed36
482e65f984de1d07b79b1ab35f7e7cb4
c5b24851a4a69d6d8c8e5bb899d3b812
33045b4ebee6dc59791628ac86531c86
9e39ba6ff80a8f380cfedb64e39b94ab
c5d0e8298c8231faacf37c39d418d250
7606abf8f18a7e1894ac806623502a8c
f35b403a015f03b9f4a7abad0ba7c291
3fce16d0d5d0004263f8f15e3023b50b
7e33f2219c42f466b48669da84287ee9
823d53fd12a2af31fb75df7959efc186
cb7d46f2edbb05fdc2d46c12e6167714
fa3afefc843f28b1d2ba2780da5feb92
2379b57e8ae3e630fd05fe994c20bd5c
a2469be912c6cb69aecde7af497c5524,afe72d2ef971f6330b38c9f1ab219910
4f31add4cfefcf37ff18121282aa9b7b
2ee79dd0bc121f0704f972c744643feb
fc5de224caaa5ccfa9abce15370fc950
c6b56eade24f7a81fb4e3e7f92c27b47
e0ca8ccc957022a3c7ea3ceeb513ca23
97fcd09c8748af89252a66ae63686ee1
8e4d39a1e12d173da83ba92224917e76
ae1cb4efb580320ac44784e5b53a5749
c5b24851a4a69d6d8c8e5bb899d3b812
b31953accf1e2c2c03a21e525ed12afb
5ea94b958ef8970cc005d4248333081b
7527d548c66497d1ab33fc17bcd2b9b8
11a3163af56c93d3f02ccd881a153861
559a27d0f30ea0b131cea62ab9546c86
a4c2d4207408f14b4ffdacae20ca08f7
60c7819938d980c38e8cea68a6049afa
577de6021bda1e0ceca478e31f8bfc87
0ed3ab81f348ee25c87f92ab4087ec5e
65066e0d171be18d92f1e601aaa36260
49d1b669f1408f5495fc342e5a367165
889e1f826bc1ffa8c58fd538724ee218
9723f55e165766df638601db2c550e17
21fbe3cae634ef91e796092bd50e14d5
f6951cefbe653efb7a0fcf3ae0885d11
2ef791a0727170fed776315c599cc310
fd11c037678755346d5d87939e8121ad
d953147cd0d4a73585e0501bde56cb68
5480d2bfd771ffcd060f512849da42c4
80ea838bd21ddc44585db6b08c3e8d82
7da26a6a112fc0a4853a40d34e3ddb4d
902d1160aeb6b79c0084415871d8aa96
7f9159a0d78aac2a2a88e312e4448a32
98b6a6f49e75a1c7367ef6358fc8107b
8812b05556753b1ed2a2f439baddfcd1
0271e16d9cf6af3616c7f5646f1ed64b
d7ddb097e2138e1c72563b6ccb2af019
fcb40c5656a7d53a0a31ce9a45134954
036972ce68087074133e95ee76713f2a
db65748051ef42ca5159d4f5f675cd66
bf93f3cce7b449c9fe5cd623d3d99858
901a10ed899d9c02502087c7819f38ea
29e5faf44e37519ab55b95e5b4b87d21
1b0f7157d4a4cffec54129bff35cbd1a
586db98defc0129ea0f7f11f4917bf04
27cf7abf04f836c0fad4b02c2c5eb1cf
a04fc54f775f2776321673d69c80d4ea
ddfd36cbf7eec6cd62016fb8608a51ce
a1c469d02bf1c38afb04a490e89db776
5a06c33950409e43f713d56f70f1b303
ccf99ee92991020228083dd81fa4e550
b09a79d6ad6b026bef05c78645335902
df1733992db1b4645207a5b06a1f953a
bb0692d4a7e038da83171b7279c9cdba
d953147cd0d4a73585e0501bde56cb68
d192e8eca0b215e58fc76ed5e7cdb8d3
e5aa65b4162a6c0b5f39dd20f8a53e83
61f3e3dbd56a5e8c134c3f290115b71c
07fc67e89397ab658cde9e3dc4c5640e
35aed298a6fe17790be0ce24a102e4b9
119c970e7ad443c12043caa63b6fe7dc
81fee0b2c40714d16eb1f524c1d0416d
353093ebf7e589f08444bd296fa44e97
019d0e5eef638d61ba480f6e3d58d003
f375fcfa1a0d974c2792f50a9439fd09
019d0e5eef638d61ba480f6e3d58d003
ccf99ee92991020228083dd81fa4e550
426dbfb07393dab2ca6440d4afff6c25
426dbfb07393dab2ca6440d4afff6c25
854c96d3f08e9a639c50b0b06ff2ad66
3e9eacd0722f65d9b33f3b4367f01b49
c6d822cdadf581d31cc468ebad5869a8
fc792d8bb7ad8d13c97776e18c714ce0
119c970e7ad443c12043caa63b6fe7dc
65e7c40d57dac350a511664678177df9
84a89358c67cfbd28163d67eea589c27
f96c0e7252688bf0b362e95c7dc55542
4c8b5256d902115c72953d55d9a77667
f068075227855de709cd7bea20b94712
e049fd711a582a90c5b9e73f4464d4f1
4db301bedeefd96771160df867da5044
36c76df229d308d1d3267b3092398872
bcfa63831c099ac7ad457e7b30471635
8ce3da76b891f7eb52305c2103a32ee6
7b6a1ef444427e2de4568a1d78f1910c
ee1f14b3efbe3786f4c2ea50ca93c950
e46289d37fa76918074ed8119f65a5f2
6616be150340498249f27ee70f8aa47e
306992c1996d8083d53a0bdfea67bd34
c6d822cdadf581d31cc468ebad5869a8
902d1160aeb6b79c0084415871d8aa96
a1bd88629f25c42bd362429ab5c81361
d897960d3da4f72ee5dd1425972f479f
57b5f4e5596390b72b76687fb49a04a5
35bde7180b6ead5f026789cdc84fa8a6
b51aec0cfcf0eecbaf583f913cc18f3b
0d7fd55c853edf44fd716f2e5eab72da
61f3e3dbd56a5e8c134c3f290115b71c
363abace285483d5015d3d044b5bc101
47fa65303a3527559a8f4524365a5c3c
3e9eacd0722f65d9b33f3b4367f01b49,40b0229cbf83c8857e8c9e7d79bec8e9,dd416340a4613c46ed12b87717e4a8ac,a0a5dff287d5f43498a81934df34f6e1
80c33a887cb058f204da9025d782b815
7bdc8844e34db81fdde25d0ce438b6d8
f5b37c482583796b56e43bd8f5724b9b
92e6b3b8f57c8d4a768f1e5fddf14a00
507362674ccf915721cfc5d80027956d
4fc5d7c934dc22c284fadfdea0d6622b
3700221b76918b09c41c38ab7ca0d80a
5c90775712b39468a3e22b6deee48708
c9a9ecf56ee8b676d05588d2919232cd
3d90ea906736eef7c1c443555b764cbf
3cc0ee6a7988bba6286796ca0e6630ed
e2555e80b296186557426f4a05012d3c
7f9159a0d78aac2a2a88e312e4448a32
2c311bc8069feeecfd14d70897dc0877
5ca49ebb1d8ad7ccb063698fe09f76e8
44b1706c0fbc72b86c4615bb44fb9d7b
1f29f7f1b5af1d165f33e5da794bec26
056c1e7117009ae71ae33b0cc692fda6
1f29f7f1b5af1d165f33e5da794bec26
816d7568acd3d436a287b53f4d8c6559
3064174f44225659b464afe56a01625b
74d916bbe243ee0f8c06fd56801fce24
afc11567288caf51db32557dfe1cf238
89143c5189252c885169a7f7ea20e10b
cbbcb70943244bc738c5c1c0040f835a
b31953accf1e2c2c03a21e525ed12afb
29ad4e576559450a1e82bcd0b8500d28
a6fb1718e44cf177699ee9cac7177d7c
0509e4793db90b36cec505fb43d428f0
b57508a80ba85a740080aa172b5d60b1
a04fc54f775f2776321673d69c80d4ea
70e566a092167f5ee4fdccaea4af6252
7dd54d51073cbbe27a638c1e77e0c87a
32f2870925459f5ba1dcf65fee9a08c8
f16a381e577c5ea74b5e2c02a6e64a58
256d87be88861f97f85c0e9f8e5935f0
1cf4a76a3d606a74a34ed27e0f27751c
63a9e49915cae14443cb176bf913fc40
dd797073a916722a1fa66a681b5988be
bcd183c6dcdb056c8a0180703f9824c5
7e882795e09328458c852abe7acfd87b
5ca49ebb1d8ad7ccb063698fe09f76e8
7b4b0209baeb1fed155051b6f8dbfc58
8d05dbcb455bad71178026daea864db4
b5b9efebcb34dcab469ac4ec2e3e00da
1b9d847e265df28ae80d2c4b3a8b2901
06ff223a4e272c58920df2ac32142a5e
8f076ef293394c777de8d5c4fc3240ad
9120cf47d515e5c75609accc846a899e
7b4ca419f4a4c4381a36ce3854ddf1da
816b9dfafbfd91bf3d828efd5b9e46fc
ee1f14b3efbe3786f4c2ea50ca93c950
4f312b0f37bf9d86333114a4f467ddc3
36fac51b1cac71ead04dd03f4f45dcf7
b5e720842c2c1b3fb3c71309fa4434bc
a1d469adbf3bd0adc4379131d52b4379
2c1505e613c7a9861bd2d8e17a996ad0
643fb24bd380e2f181c3a958dd465591
e049fd711a582a90c5b9e73f4464d4f1
74d916bbe243ee0f8c06fd56801fce24
e1b7b88ad76d7480beb24c0e489e3034
2888fc233fe52186bdd632b250526631
725be1e44e6b5f9ebf67906a75ec9933
a81d5716b461240ff91eb40eb99a0768
4c8ba0bbff80ab81c5084f11a2549827
c521a7d8077f759012c14c6bfb531cbb
31ab065a25a21564223a898cd741e2f5
e29e1dcb51131a6ea34fee85b7e6b882
e8bb78b1dffdfe27d544fcf9228b5b7f
cc83b05076086e5e31858b1dfe2860c3
37a51512676179c4e60df9851cfe03d3
635572e7b99059adc55910638d6aba95
ffeb1c1402edd94e78f7b6c0b9ec5e4c
2ee79dd0bc121f0704f972c744643feb
9d536a3ff7d0a754c69fe5df5231d34d
72b705952c8dc1538c2e7611b9e731e8
63a9e49915cae14443cb176bf913fc40
eb89b214cbe983a4470f97aa0c4b4bcd
aa32806dcb51596555489e93f4c4340f
6895f435135caa336e0b63b1ff1eeb68
03163195705609d1cd687ab4625aefc0
f732cd2547622a112d7cf896c67a9ab2
276b9794c8a5beeb829cf3a24c4d4c33
8bd5efe2283d00e28bf9782bc49b9a7b
5c155bc8acd3d13da786a373040a240e
ffeb1c1402edd94e78f7b6c0b9ec5e4c
78ca76476c7f9ce79c4c0f4d63f80803
7eb3bb889d4a222e1d44d85cfb488b73
816b9dfafbfd91bf3d828efd5b9e46fc
63a9e49915cae14443cb176bf913fc40
d897960d3da4f72ee5dd1425972f479f
bac3ece29aae1e4d38c96add5a19da76
c350c71a1567b63b24a5bbfc6224c14f
60dec45d8b4bbda8681e85f05e979f95,4b041b8fab2bd834e6acc34a541520cb
081c152961797040930c8128122e0e00
7c5f3d7109a088df904321d3d6eb649a
854c96d3f08e9a639c50b0b06ff2ad66
35961793c02f21072b2af72e769af5f1
5ef139e5e983b02ed0f3fd3d095b1eab
e103d09f895b97f45c376a60b2c56151
b8e635be69e7ef8295f38fe9147a9d9d
c92f34dc31db156f4cd691feb313a19f
036972ce68087074133e95ee76713f2a
6767a7ed15098325f2580247363793dc
f9c0d1a6c3dea3aa02042972502d6a5e
50d670507744a147f49d2e7434d7eda3
4eb3b5c306bb256a34ccab6bed0af879
34c0788322a9be310b1ee2ef24da081d
537b2119c0d9c2899759b0ec3275e6d4
f75d36e5fcaaddcfeff0e05a2cf15f1d
65e7c40d57dac350a511664678177df9
ae45d1c21e9f38f3dc08d859f503f09a
872105665564640e3dbb2d9a24f5ced1
0509e4793db90b36cec505fb43d428f0
b5f2705bc4649da0b7af267533fe7fdf
3cc0ee6a7988bba6286796ca0e6630ed
7074f3c604d90334b9686da09378ec36
4b041b8fab2bd834e6acc34a541520cb
840a7401e8c21746ee95729fda82d540
bcfa63831c099ac7ad457e7b30471635
14850b4cd1651f79eb5235000391da47
3700221b76918b09c41c38ab7ca0d80a
7d3389fb19439ff31091b2c7a3987fb2
4c8ba0bbff80ab81c5084f11a2549827
9ed539a96c6ffd96f54f63c13fb1e0df
a1c469d02bf1c38afb04a490e89db776
74d916bbe243ee0f8c06fd56801fce24
f10a8e559deb772c2b8b8f547e38b21e
bf3c84b69ae0c29fab3dbe8b3a9033ff
bf3bab9f98cf513bd09ffe6e773ab8d8
50fd1fbccb1aa184e8cc9353207005c0
3064174f44225659b464afe56a01625b
89143c5189252c885169a7f7ea20e10b
4053bd3d913a80d94965550bc35aa633
f34424d3f47c5f6d60e146589e3e7e20
a0a5dff287d5f43498a81934df34f6e1
c40990246bd03c18ef187a6bd514d464
41714dc8efa72523fa91c4061ed0ced6
f62e8250143a61e087015b0677894932
6133600a0f61d01e5a6fec07a5ae09aa
d953147cd0d4a73585e0501bde56cb68
3897bfee9eaea606217f4b78e80d18cd
3a91a445ab0b14de66d30c0b7ddc89ca
a0ee6406194f05b6e21a3b3930dd1eac
66710a5755b499660b59a3c875cff124
29ad4e576559450a1e82bcd0b8500d28
74d916bbe243ee0f8c06fd56801fce24
2ef791a0727170fed776315c599cc310
97fcd09c8748af89252a66ae63686ee1
618a5bd84683d8a3cf292f5169e72ed5
1809339e95e54406b183b5c14316b812
31bf75e7c8254139fdd3e35811cf4d9f
8543f999bfcf05ee885408f70d7a87bb
3fd7d892b0ada9cf0f7c7ce963bec157
ee079757ecd9b7c73e31920c6cd4067f
571c9d7cb9dc4e76611c09311fc5edc2
823d53fd12a2af31fb75df7959efc186
f9c0d1a6c3dea3aa02042972502d6a5e
227d508c1de10b3271147a2a70b0abe2
db44fc95101c2e96c74843de12819506
1b0f7157d4a4cffec54129bff35cbd1a
fe1ee42973d48bc63fbee3c6d9f78160
ca954af7a2442530914fcfa720c724fe
577de6021bda1e0ceca478e31f8bfc87
b59706cad5c7c00a4b7316526096bd09
16a826f6cced50d0e3f1aebafeaabf8c
a63caf3220978f6f673292f79a493e7a
0414b25537824df6303343bf8a0bce76
3d2b57725175988984cb434333920afd
ffeb1c1402edd94e78f7b6c0b9ec5e4c
ea84fb80acfa95bb725afad25ce26baf
816d7568acd3d436a287b53f4d8c6559
8432e000ce9d8fc9acf382803950677f
1486ccdfc852a4c118ab3463b620a466
0343638604d391dff92e0c9fcfc9cb81
458805b20fa284b8076ed65b0dd04335
353093ebf7e589f08444bd296fa44e97
127e8b69619faf7c18e0da6c7ba9bd5b
21fbe3cae634ef91e796092bd50e14d5
7dd54d51073cbbe27a638c1e77e0c87a
2916e9cbc27965e261f8eb11089e584b
bb0692d4a7e038da83171b7279c9cdba
e6ce399afaea9e9f7ef02c6ddfa1855f
3625ef5088c965b7684d429c0200daef
0c2126a38c0ed90c78862f4d35c122a9
d149059cefe1e067a06889abaf6ae36d
4d78c3506e84b7ba8a15ef5dd8b1f245
7cc6000de2268586c1221ee6a1efee37
ebc1d84a9f5f8e64b19c3d9c11c3fb8d
635572e7b99059adc55910638d6aba95
107a1659879414884064e305372c5631
051c68bc60c123ce99f5008609efbb7d
823d53fd12a2af31fb75df7959efc186
53198831c219ac4fb6916145a41a94cf
643fb24bd380e2f181c3a958dd465591
53e0a337dab988e3ff85d0fb6f5e8dbd
3d9905544d3c14216d56e14789166e57
bded82f85592223993fa54de9d509fae
fe640b2dd98e4b1ab800169645b5562a
5be77ba5aa6a1d99f764ad6356ad4d52
0271e16d9cf6af3616c7f5646f1ed64b
9e392161d38fc307605c2cda6ef2af81
1cf4a76a3d606a74a34ed27e0f27751c
8432e000ce9d8fc9acf382803950677f
d08912a6eb92812348a55698010f3871
d6ab8077608f5bf6ed64e735ff17f1ec
4053bd3d913a80d94965550bc35aa633
725be1e44e6b5f9ebf67906a75ec9933
265152567ab5b818adf0ce68801b8fa2
81fee0b2c40714d16eb1f524c1d0416d
963c824e0b07a3f98f301e3e7cd442ee
363abace285483d5015d3d044b5bc101
902d1160aeb6b79c0084415871d8aa96
9e39ba6ff80a8f380cfedb64e39b94ab
df81af52d06780671644c62b3545e350
639c075557bb940cfa7e6cb90f1d7dfb
0d9d6fa94ae5216d9bcb9052f50f96cb
18d01ec07210c571629cfe9d55b98026
1bf141bf3e9985c89769c6d16c1cbfbc
ca5b0b284a41f95cc7684e3e791e5e43
52e259b808c818e4247af81655f0e195
fe90159c19ea82a30c75f42b5fe25fc1
e1b7b88ad76d7480beb24c0e489e3034
8f0626f20824a22fb383950427bfdf1d
98ac31d4329f872502c152c3cdde4087
69c03212aced107aa6a570d62cddf377
8432e000ce9d8fc9acf382803950677f
9fbc27fd621cf6886695185ff3a21216
7d2eb6fc914780401932798a3c8a66d5
8bd5efe2283d00e28bf9782bc49b9a7b
941095c6f1ea8aa7f2db35cd15d4526d
5e5903ca525b51c4e1ca692e523d9af5
2e5ef6887eca86d5eeaac00e40d564aa
279d1f9de9e50356e48457ae34e25e27
6ef8606071d6f96d49d2e6697a5b2407
b2e7cdbee461467dfda0f216f677b370
677ee59fb5726818d18024fc01dd6bce
53198831c219ac4fb6916145a41a94cf
eb89b214cbe983a4470f97aa0c4b4bcd
4a221a726ab64fe169ba2b2a4603b361
3d90ea906736eef7c1c443555b764cbf
618a5bd84683d8a3cf292f5169e72ed5
df1733992db1b4645207a5b06a1f953a
30fd9647914621e222105852429b2191
97f313290a9dc16097cac7734c1637cc
a30d42b1b088c84c2da2ce16fca5b798
edaef13be77ad2a413af6bb4498b1ccd
35bde7180b6ead5f026789cdc84fa8a6
7d3389fb19439ff31091b2c7a3987fb2
f96c0e7252688bf0b362e95c7dc55542
fd11c037678755346d5d87939e8121ad
7606abf8f18a7e1894ac806623502a8c
49e5abc6b9b578b95b213e43786fc023
f75d36e5fcaaddcfeff0e05a2cf15f1d
127e8b69619faf7c18e0da6c7ba9bd5b
1ac1818c94bdcbfbefc0f582a0b25136,35aed298a6fe17790be0ce24a102e4b9
53198831c219ac4fb6916145a41a94cf
a30d42b1b088c84c2da2ce16fca5b798
48e215170f43f1717d978f0fd56a92fa
7aa3ef507105b4b44498ca9e25dce68e
4d9ed289a439c416bb1619a3b408930d
d92a2254790d518b031c99fb3b947641
714e124d2cbae5e408b52aa9c65d61b2
e88457aa452f777eef85fbbfd95ec85e
a7cec9cad4df1525a31bdfc0f45ae03e
a1bd88629f25c42bd362429ab5c81361
efe3b79b8dfbc5534a37c67fd08e3fe0
e22df26ec5200ae93010595f0677c1a6
d08912a6eb92812348a55698010f3871
165388c7ec7fa6e5462d4a1c8df48d8b
c6b56eade24f7a81fb4e3e7f92c27b47
5e793aac5bf49d8e56924c19e00e659e
5dbe282f688ec08e9f7f0803cbefc372
35440f661f1ad24b3bc9ccd845ab1036
3fd7d892b0ada9cf0f7c7ce963bec157
637ef19ad1a589d4a570ec593a7a34a5
a30d42b1b088c84c2da2ce16fca5b798
c9d44105b828c6f72ec5db6d47b8b7b3
9e72c3298677eb33974cb7e92ef0a6b7
a1d469adbf3bd0adc4379131d52b4379
b788a1dc78950ebceef7adb6ff5ff49b
618a5bd84683d8a3cf292f5169e72ed5
add9d2ecffc679c3b016dbaa35398357
352d194baed18d1ace514dd0d01fa63f
687f704d25a29f23c2dbf2a0b2d2dd78
fc5de224caaa5ccfa9abce15370fc950
06efd45528199414f37602fc26b1e5a2
7da26a6a112fc0a4853a40d34e3ddb4d
e45f7c307e67b13f457504ce1e93adc4
5ea94b958ef8970cc005d4248333081b
7c960ceb395435846ac66ea3086c970d
984809425e10ef00c06559d5faba96c1
c63a50793c8bc85164ca67185bbd5ce9
b59706cad5c7c00a4b7316526096bd09
2a2459a08478798ff691292ae5b3ca24
b33ad589799efe4f0ae9a5bb57c2c734
4b0b15db52831c57ce89a363299c6861
34c0788322a9be310b1ee2ef24da081d
2aa5b0d0ace3a1542fba29464ce7f21e
bac3ece29aae1e4d38c96add5a19da76
ef280f9608bfc2c73cc1f238db25060a
8bd5efe2283d00e28bf9782bc49b9a7b
7e4f83129707754f57b6d7de87712a63
81fee0b2c40714d16eb1f524c1d0416d
8b1d9486c7ab2722dfa7cf855cc6e54e
8b8698cc1746ad3920c7589debfd21de
3e9eacd0722f65d9b33f3b4367f01b49
5ea94b958ef8970cc005d4248333081b
11a3163af56c93d3f02ccd881a153861
ee060398a75b39b2a03c9add1f7978e1
96ffa1835f0d6566e86384c96b78b9b1
05a2c2d6e5535bdf6a24d481273872c5
161c299ee26046641e7ab7453642e631
687f704d25a29f23c2dbf2a0b2d2dd78
7bdc8844e34db81fdde25d0ce438b6d8
c1873377ef35a86716e7db29fa78afab
6d7e042a000deca140c330ab99896ebd
db44fc95101c2e96c74843de12819506
5571d29c100d4ecb876ce740ec5a230c
98ac31d4329f872502c152c3cdde4087
ae45d1c21e9f38f3dc08d859f503f09a
90d2a26e0963b293fefd214569d17cfb
8dd81773b5d03c3f4313e80cc0f5ed0f
269735d3c130ac7f21444a8f16977d9b
acaa67e0837a1c506b4ee33778c3d34d
7d2eb6fc914780401932798a3c8a66d5
e5aa65b4162a6c0b5f39dd20f8a53e83
e78d8dbdbec094b48888c2a9bdf3db31
7074f3c604d90334b9686da09378ec36
53198831c219ac4fb6916145a41a94cf
5480d2bfd771ffcd060f512849da42c4
8b1d9486c7ab2722dfa7cf855cc6e54e
38ab3499c5cf480879f7cf34567f24c0
ea84fb80acfa95bb725afad25ce26baf
ece4979927cb7d661e2ce393d9084bf1
50d670507744a147f49d2e7434d7eda3
959c47552fda50d8cd039f60be32e643
ae5c3471f12387be2adebc7922067ff0
8e9d2fe0a1ea2cbff94ceb59acf05afd
a7cec9cad4df1525a31bdfc0f45ae03e
faf9d9dd07e9be093311e0eba21182b1
6c602f815679f5a7ea6eff8574de6c28
e2026b3693a8d0d1ac381b2541831b9f
66710a5755b499660b59a3c875cff124
7d3389fb19439ff31091b2c7a3987fb2
458805b20fa284b8076ed65b0dd04335
77fd740e226dd625f8b98f91ef202eb6
2c1505e613c7a9861bd2d8e17a996ad0
3a91a445ab0b14de66d30c0b7ddc89ca
66a83e45f28f5609f6dc6f9bc0724d06
9120cf47d515e5c75609accc846a899e
1a39b5cec567da08fdd8dd0e2661d875
cde35f01dcc2e3b6fb1aca36ae0ee237
aecb5c9cf10ec6d43cf1377ac5f5c728
8a7ab1f90a61bc0baca9c1b02c2b88d9
731481a51f92ca1165fd56cc07a85bb9
b896fec03441019f564909b07db0b3d6
984809425e10ef00c06559d5faba96c1
37a51512676179c4e60df9851cfe03d3
9e72c3298677eb33974cb7e92ef0a6b7
8cfbdabb841dfef12e3e7d25a29a2d1d
b26b42fa48cc68886ca0018d9893fcb5
430d475b8859a9d82728b9dadb553fef
388a5a3fc874395eaa19dc989099e872
fc792d8bb7ad8d13c97776e18c714ce0
dd416340a4613c46ed12b87717e4a8ac
93da6de45bac6556d559e27278cb6e54
939f2baf99db127e01ec6fbde100de5a
5a014e82fe823aebc64152c65ac86a46
6062a9e315071d4cc1e582a36cc90e8b
ece4979927cb7d661e2ce393d9084bf1
c1873377ef35a86716e7db29fa78afab
06ff223a4e272c58920df2ac32142a5e
a63caf3220978f6f673292f79a493e7a
3a91a445ab0b14de66d30c0b7ddc89ca
0459580538600b2c4ff56fbc2dda3f8d
941095c6f1ea8aa7f2db35cd15d4526d
0da3cbbdbf7158b0981ee29b3d686ca6
52e259b808c818e4247af81655f0e195
72cb8cb9d32d604d1863c8fa76a7bcfa
4db301bedeefd96771160df867da5044
66ad7e68c5579f0e86e19fb0bcb59c9d
ab3d2eb28cbc976e2fafdad1b7ebd482
301ab3d7cd81d361b8bab86f6bf99d95
e45f7c307e67b13f457504ce1e93adc4
695a6f4d2a019add2c2ea22bfbb3a9e2
f75d36e5fcaaddcfeff0e05a2cf15f1d
2dfe826e824be7748fbe6417ca946a1f
cc83b05076086e5e31858b1dfe2860c3
b26ea9cb75c69197895f8e9c9aa819c8
1a39b5cec567da08fdd8dd0e2661d875
66ad7e68c5579f0e86e19fb0bcb59c9d
b7499b38e46510bbcb3ca3606dfc4091
ebc1d84a9f5f8e64b19c3d9c11c3fb8d
31bf75e7c8254139fdd3e35811cf4d9f
8bd02321f3bffe00c04a663bda6fe244
bf93f3cce7b449c9fe5cd623d3d99858
7aa3ef507105b4b44498ca9e25dce68e
49e5abc6b9b578b95b213e43786fc023
27f5d5b8b4e2bac9a44cb4e4652b471c
27cf7abf04f836c0fad4b02c2c5eb1cf
3d9905544d3c14216d56e14789166e57
97fcd09c8748af89252a66ae63686ee1
a30d42b1b088c84c2da2ce16fca5b798
8ce3da76b891f7eb52305c2103a32ee6
276b9794c8a5beeb829cf3a24c4d4c33
b2f82c344a844898d26953f64df2ff83
49c66e069adb221d74fb741237f007f8
d92a2254790d518b031c99fb3b947641
503a979ce10f2ec8b7ee25871f90e010
6e280b80646b36652853802041e84447
165388c7ec7fa6e5462d4a1c8df48d8b
c022301d3e96a8b59a0370c57d285f34
3d2b57725175988984cb434333920afd
e22df26ec5200ae93010595f0677c1a6
a93e88e0cd314c1ed59649b720f9c411
e0ca8ccc957022a3c7ea3ceeb513ca23
a04fc54f775f2776321673d69c80d4ea
5cd3ceb7c0ef7b92a7c07f1205565d55
c9a9ecf56ee8b676d05588d2919232cd
f5b37c482583796b56e43bd8f5724b9b
3ddb4ca350c1eb1992bace409bb50396
1e22dbbe4fb47a2c712410793836be00
b51aec0cfcf0eecbaf583f913cc18f3b
2e493bb63e94c96bed31ece791476c53
3aef2dc723538f03b26af98c33258669
6033b7f65f269e4f50b97e9fd4d470b8
bac6597d8d6c0ca72075c462c4d17363
e29e1dcb51131a6ea34fee85b7e6b882
b73d8629ae2d008a8184b8761b4a9c87
9723f55e165766df638601db2c550e17
35ce84e828c308566b763a7a21450245
b5f2705bc4649da0b7af267533fe7fdf
4b041b8fab2bd834e6acc34a541520cb
9d5e7952ff3ecce46cf7a6a76837e51a
e78d8dbdbec094b48888c2a9bdf3db31
1a39b5cec567da08fdd8dd0e2661d875
52e259b808c818e4247af81655f0e195
b758b0b14bbc1e1ad613914b959275aa
74d916bbe243ee0f8c06fd56801fce24
86ed173774a1f3ef085283026d86353d
157d68a0e73262e443ad843e7d29195f,4f312b0f37bf9d86333114a4f467ddc3
45e0b783d65278cfe5de24ef1e3a8e5a
7527d548c66497d1ab33fc17bcd2b9b8
637ef19ad1a589d4a570ec593a7a34a5
4db883d0d82be0f97e533f25e5dd1363
bac6597d8d6c0ca72075c462c4d17363
0e832897fa736c9a232552dcecfa36f1
b3f3a8609446e2af6513baef5f7ba8fa
9e248f56b5297c75edb4ad937b82c1fe
b995567c39f8f378112456f0b1594c86
32f2870925459f5ba1dcf65fee9a08c8
45d6388b4664c0bcf33aa878b230998c
f805d549425c7328c40729b84606ba07
503a979ce10f2ec8b7ee25871f90e010
9c4007d4719272d62f8dbe7ee63ff2fc
d190cc378aabcfdad876818bfd92a118
1809339e95e54406b183b5c14316b812
86ed173774a1f3ef085283026d86353d
84924384c3bbec5b6d66f549cc7c9246
9398961707509100fac0c849a6b3d5d7
b73d8629ae2d008a8184b8761b4a9c87
dcd815cb3dbd401112ab1a91fa9ef3a0
92e6b3b8f57c8d4a768f1e5fddf14a00
3a91a445ab0b14de66d30c0b7ddc89ca
281f658f4f680aded3baefa9d1512146
3da304722fa16d03f50a47000f7ae920
0e0c96f2cf41b938cca9852efb6a3393
8fa16044e151faa4c7340d13f083c494
1e6efa73875ae5b85c8874c7e6c11f4d
ee079757ecd9b7c73e31920c6cd4067f
9d536a3ff7d0a754c69fe5df5231d34d
ce692dd8417c8e34746156ce9b799e91
3aef2dc723538f03b26af98c33258669
3ca114ffea4bad23501640afaa30013c
8d05dbcb455bad71178026daea864db4
96ffa1835f0d6566e86384c96b78b9b1
173920288064a7bf27bcc654eb63323c
bb7c0faa9029b682b32e0997f3cc7b70
5c155bc8acd3d13da786a373040a240e
7e4f83129707754f57b6d7de87712a63
11858f55795ea2ddf27da80247d8793d
7543b283afa6490c3fd2e572d50dac37
50fd1fbccb1aa184e8cc9353207005c0
1486ccdfc852a4c118ab3463b620a466
ee060398a75b39b2a03c9add1f7978e1
3a91a445ab0b14de66d30c0b7ddc89ca
352d194baed18d1ace514dd0d01fa63f
56b28258fb8ccdbf1f5d4801346a47ca
00ec5bcf5cdf6ac416e600b2bef9a7c5
051c68bc60c123ce99f5008609efbb7d
4053bd3d913a80d94965550bc35aa633
cc634c526fe4da575eac6077a3071644
ee060398a75b39b2a03c9add1f7978e1
6895f435135caa336e0b63b1ff1eeb68
29620dc4b82887160ec1629b3e5c6edc
f16a381e577c5ea74b5e2c02a6e64a58
ae1cb4efb580320ac44784e5b53a5749
2916e9cbc27965e261f8eb11089e584b
9ed7bd905ff8885aae62007e5860d5e1
4fbb2dd51a4f547e7672d806819f737a
f9c0d1a6c3dea3aa02042972502d6a5e,583b77699d72eed9181261b8b8c9aef0
73ad0ff1e72011b6c9c07f19a8c4f09e
39cddf666d46468a97a2029a87461764
878ffeff84f1422cc50ee869bbc236bb
fe640b2dd98e4b1ab800169645b5562a
c942b22440dfbbf083726d8b843ab2bb
c5b24851a4a69d6d8c8e5bb899d3b812
38ab3499c5cf480879f7cf34567f24c0
dd746d62539d3641ccee848781413762
5dbe282f688ec08e9f7f0803cbefc372
1e22dbbe4fb47a2c712410793836be00
878ffeff84f1422cc50ee869bbc236bb
44b1706c0fbc72b86c4615bb44fb9d7b
3eb167d5ba1a709b3728fadc859f2dc9
b26b42fa48cc68886ca0018d9893fcb5
6133600a0f61d01e5a6fec07a5ae09aa
b3a19fd58ad492f377431c4000e947b1
7a039abc3278bd040255b3b020b8a305
bc00cf32fdfe9944f7b4b92ad9596035
2e5ef6887eca86d5eeaac00e40d564aa
3442cebc305fbdc04afd63d9e4938a57
92698f95c3f6fad49f138d3a500b24c1
fca1f2a2526124de979f3c15a53bc084
f38a2fe99994feb158aa4a165cca1e64
4b041b8fab2bd834e6acc34a541520cb
c3bde1bd54b7318ec7fd8ba0a5ef2799
39cddf666d46468a97a2029a87461764
f75d36e5fcaaddcfeff0e05a2cf15f1d
948c612f0e8393bee48d6ec07b10973c
922594eb52879d4627845a02df136f12
f62e8250143a61e087015b0677894932
6639d0ba46faea4e76013e7956eb4497
dcd815cb3dbd401112ab1a91fa9ef3a0
92ebe5f3368b52fa143ab6a1b25d9b09
959c47552fda50d8cd039f60be32e643
a6fb1718e44cf177699ee9cac7177d7c
154392ec995e88a7fc95e4cce6af9fb2
f96c0e7252688bf0b362e95c7dc55542
e103d09f895b97f45c376a60b2c56151
586db98defc0129ea0f7f11f4917bf04
173920288064a7bf27bcc654eb63323c
e049fd711a582a90c5b9e73f4464d4f1
583b77699d72eed9181261b8b8c9aef0
d79f1283e52a2c0ccf82c9516153f8cf
b3f3a8609446e2af6513baef5f7ba8fa
96ffa1835f0d6566e86384c96b78b9b1
c63a50793c8bc85164ca67185bbd5ce9
dce725e1c5ecf28cdf26d89b0b796f8b
2c311bc8069feeecfd14d70897dc0877
f96c0e7252688bf0b362e95c7dc55542
3d9905544d3c14216d56e14789166e57
6133600a0f61d01e5a6fec07a5ae09aa
dcdf26f3c7f87440b56877744814cd88
56b28258fb8ccdbf1f5d4801346a47ca
c022301d3e96a8b59a0370c57d285f34
bcd183c6dcdb056c8a0180703f9824c5
68d0e9384068227713f7e37dfcc9d0e9
c843f95b066d1e84cf5be5e354efebd7
391c2ea7ba645d4107db89ac008ad908
4a221a726ab64fe169ba2b2a4603b361
c843f95b066d1e84cf5be5e354efebd7
54155858ff0ff417ff7f901493e8d80a
3897bfee9eaea606217f4b78e80d18cd
bac3ece29aae1e4d38c96add5a19da76
4fbb2dd51a4f547e7672d806819f737a
baca875e1c185711a26e02177ae10a5d
cc83b05076086e5e31858b1dfe2860c3
279d1f9de9e50356e48457ae34e25e27
5e342630b24ba50178896af11e67655c
0d7fd55c853edf44fd716f2e5eab72da
9d536a3ff7d0a754c69fe5df5231d34d
056c1e7117009ae71ae33b0cc692fda6
bad451268583315c8689ea4e737b6c26
dd3d6e9ada3c64b33eb230ecd0c570c4
4e953a9700fc3a4de58eb3b066eb4c74
1b0f7157d4a4cffec54129bff35cbd1a
9ed7bd905ff8885aae62007e5860d5e1
227d508c1de10b3271147a2a70b0abe2
98b6a6f49e75a1c7367ef6358fc8107b
fcb40c5656a7d53a0a31ce9a45134954
44b1706c0fbc72b86c4615bb44fb9d7b
35961793c02f21072b2af72e769af5f1
430d475b8859a9d82728b9dadb553fef
b7499b38e46510bbcb3ca3606dfc4091
60dec45d8b4bbda8681e85f05e979f95,4b041b8fab2bd834e6acc34a541520cb,ef280f9608bfc2c73cc1f238db25060a
7eb3bb889d4a222e1d44d85cfb488b73
d967e2a9d2e8cdfa87e7f635136f8112
45e0b783d65278cfe5de24ef1e3a8e5a
00036b0d076874775f025b132626a224
4fbb2dd51a4f547e7672d806819f737a
30fd9647914621e222105852429b2191
f20c1b43cb9ce21b83778e28fa70801e
45d6388b4664c0bcf33aa878b230998c
672403cdad2280c224c48a86781ec78d
73ad0ff1e72011b6c9c07f19a8c4f09e
fe1ee42973d48bc63fbee3c6d9f78160
a81d5716b461240ff91eb40eb99a0768
0c5fe72a6de028fd69d82ec673b761d2
5bec040b123435df0d1806ddb50cbe9f
f8d344bb4d8c6d9ecfad6577f56d5678
05f86807792bc5668f250749a1c52bda
0414b25537824df6303343bf8a0bce76
922594eb52879d4627845a02df136f12
92e6b3b8f57c8d4a768f1e5fddf14a00
75043c96c729a77d1c7d40d326cc75b4
9937b8d3200640feb7666f6e57aa48d4
542bfb8262044fbb1bb33ce9d3793080
75043c96c729a77d1c7d40d326cc75b4
672403cdad2280c224c48a86781ec78d
d92a2254790d518b031c99fb3b947641
6d0cd68ed8878927cf202b140f1d43c9
07fc67e89397ab658cde9e3dc4c5640e
7074f3c604d90334b9686da09378ec36
5ca49ebb1d8ad7ccb063698fe09f76e8
3ddb4ca350c1eb1992bace409bb50396
056c1e7117009ae71ae33b0cc692fda6
a1385619e5caccf4b3b83d393c81642d
3626a5b24d53f51320b211356d251f8e
31bf75e7c8254139fdd3e35811cf4d9f
36fac51b1cac71ead04dd03f4f45dcf7
df81af52d06780671644c62b3545e350
d79f1283e52a2c0ccf82c9516153f8cf
f805d549425c7328c40729b84606ba07
2ef791a0727170fed776315c599cc310
53198831c219ac4fb6916145a41a94cf
54497a230f6a4fc29eda3e81a537ac11
49d1b669f1408f5495fc342e5a367165
013964144ca0a275fdccb11561d23fa1
6d0cd68ed8878927cf202b140f1d43c9
92698f95c3f6fad49f138d3a500b24c1
6a04ee45b8f4727ee9b5bcee145edfa1
8a7ab1f90a61bc0baca9c1b02c2b88d9
56b28258fb8ccdbf1f5d4801346a47ca
1f29f7f1b5af1d165f33e5da794bec26
d190cc378aabcfdad876818bfd92a118
dd746d62539d3641ccee848781413762
61f3e3dbd56a5e8c134c3f290115b71c
6895f435135caa336e0b63b1ff1eeb68
8dd81773b5d03c3f4313e80cc0f5ed0f
0ed3ab81f348ee25c87f92ab4087ec5e
5ec4dc615e90dc940319defc249e5912
58887a74b1a7408d67f6e510b205253a
8a8e65ab8509f439685567d40ea9fa0d
7e33f2219c42f466b48669da84287ee9
8fa16044e151faa4c7340d13f083c494
3897bfee9eaea606217f4b78e80d18cd
537b2119c0d9c2899759b0ec3275e6d4
5ec4dc615e90dc940319defc249e5912
80c33a887cb058f204da9025d782b815
2b5ebea49fd1a7a8a8b94a10d25f0ec5
c521a7d8077f759012c14c6bfb531cbb
308285789caba675b139eb73d40bab4f
6033b7f65f269e4f50b97e9fd4d470b8
7bdc8844e34db81fdde25d0ce438b6d8
d03a1d460db0681e17d2fee4cd66335d
a9df6c8208e4ca184b689d42b99ea1cb
77fd740e226dd625f8b98f91ef202eb6
ed49e9c4c6a3f1169175a50ce27cc183
2916e9cbc27965e261f8eb11089e584b
14850b4cd1651f79eb5235000391da47,f75d36e5fcaaddcfeff0e05a2cf15f1d
afc11567288caf51db32557dfe1cf238
f6951cefbe653efb7a0fcf3ae0885d11
66a83e45f28f5609f6dc6f9bc0724d06
5e5903ca525b51c4e1ca692e523d9af5
b788a1dc78950ebceef7adb6ff5ff49b
e2555e80b296186557426f4a05012d3c
2aa5b0d0ace3a1542fba29464ce7f21e
889e1f826bc1ffa8c58fd538724ee218
51d345811357ecfeb79ba814e56d4fc3
6c602f815679f5a7ea6eff8574de6c28
aefda5b55ebb20af07751f2d7373de46
b09a79d6ad6b026bef05c78645335902
bc85909fa786f72bb236a56a8f17acd6
e86e11d6310bd20eade2c7de37b6595a
50d670507744a147f49d2e7434d7eda3
e2555e80b296186557426f4a05012d3c
0cbd2d21319244a40e32a82d6e227afe
cf5f59646b9ee163bbb9c5bf55e7e39e
fdfbc6c05521ff446e9d20449213284a
6c602f815679f5a7ea6eff8574de6c28
dd3d6e9ada3c64b33eb230ecd0c570c4
93ebd7da27d17b67cc9a82404a0765d2
bded82f85592223993fa54de9d509fae
714e124d2cbae5e408b52aa9c65d61b2
f08b12a6e95cf6163c524ef687d61fff
311cf3a64ca7218c6c6eb7e9bdd18782
0c0de09b42bf2d54b04912c9bf635515
6ef8606071d6f96d49d2e6697a5b2407
d149059cefe1e067a06889abaf6ae36d
7543b283afa6490c3fd2e572d50dac37
92698f95c3f6fad49f138d3a500b24c1
e2026b3693a8d0d1ac381b2541831b9f
5a014e82fe823aebc64152c65ac86a46
15a89725f831a8cd0e0594c82f2afc91
00036b0d076874775f025b132626a224,45ce9f6602073c6df14af4c53f61b484
682268b74cf72bef28b3a2b697524f64
36c76df229d308d1d3267b3092398872
8543f999bfcf05ee885408f70d7a87bb
7abd4e2f75b243a853a8636973402439
6ef8606071d6f96d49d2e6697a5b2407
583b77699d72eed9181261b8b8c9aef0
bc154087659431c11af968bbc165f79e
e84fb53e9aa65d7b24f6da448ef66c4f
4b0b15db52831c57ce89a363299c6861
9366d77a7b7a2fc5c33d1a02ea8a82da
05f86807792bc5668f250749a1c52bda
b5b9efebcb34dcab469ac4ec2e3e00da
4eb3b5c306bb256a34ccab6bed0af879
72cb8cb9d32d604d1863c8fa76a7bcfa
d7ddb097e2138e1c72563b6ccb2af019
537b2119c0d9c2899759b0ec3275e6d4
734df183f70f56af8c738f1f51b2d2b0
18d01ec07210c571629cfe9d55b98026
fcb40c5656a7d53a0a31ce9a45134954
54155858ff0ff417ff7f901493e8d80a
a0a5dff287d5f43498a81934df34f6e1
0e832897fa736c9a232552dcecfa36f1
ca954af7a2442530914fcfa720c724fe
2acd298ef2c554aa58ea72759ffb5531
49d1b669f1408f5495fc342e5a367165
cacd5b8ed67e9e94a289de0ac25a8ea5
80ea838bd21ddc44585db6b08c3e8d82
cb58e48b611cdedea041a63e53b3d600
991844d4a0b1784c89f14f0c2c9cd19f
527cf752f6a0030b3347f0a02f9c8ba8
9e39ba6ff80a8f380cfedb64e39b94ab
81260a309f8fb7e18d5d7937a1718ddd
44b1706c0fbc72b86c4615bb44fb9d7b
fb58f86d024e5aa4c7d33752428997aa
3e9eacd0722f65d9b33f3b4367f01b49,f08b12a6e95cf6163c524ef687d61fff
11990aee734595455a6fcfe54eb92205
0343638604d391dff92e0c9fcfc9cb81
3626a5b24d53f51320b211356d251f8e
d190cc378aabcfdad876818bfd92a118
45add99671a0f66b8d2b7098f89fc72c
3fce16d0d5d0004263f8f15e3023b50b
ab3d2eb28cbc976e2fafdad1b7ebd482
b758b0b14bbc1e1ad613914b959275aa
97f313290a9dc16097cac7734c1637cc
ed49e9c4c6a3f1169175a50ce27cc183
f8d344bb4d8c6d9ecfad6577f56d5678
5e342630b24ba50178896af11e67655c
a0ee6406194f05b6e21a3b3930dd1eac
2dfe826e824be7748fbe6417ca946a1f
11990aee734595455a6fcfe54eb92205
507362674ccf915721cfc5d80027956d
2a630a08a4f592215e5f0661960aabf5
9c4007d4719272d62f8dbe7ee63ff2fc
840a7401e8c21746ee95729fda82d540
dd797073a916722a1fa66a681b5988be
ebc1d84a9f5f8e64b19c3d9c11c3fb8d
8d83428976f483e5e92673151f336c6e
baff2f8123d5c6c13585237aee6cc7e9
6394940445dd407a39da9df310337b7d
c3bde1bd54b7318ec7fd8ba0a5ef2799
bba63cbc3e68d767fe13e3e609f0d7b7
872105665564640e3dbb2d9a24f5ced1
4bfaa99566f1f39a2986e859562f18c1
388a5a3fc874395eaa19dc989099e872
7b4ca419f4a4c4381a36ce3854ddf1da
58887a74b1a7408d67f6e510b205253a
74d916bbe243ee0f8c06fd56801fce24
8f7723a6462f1ed308efc9010d02f279
6639d0ba46faea4e76013e7956eb4497
169365f1873a0855b7acd5c59a8fb994
7c5f3d7109a088df904321d3d6eb649a
9a7ed6b4667075503f2c3ee97cbf29d1
00ec5bcf5cdf6ac416e600b2bef9a7c5
3d9905544d3c14216d56e14789166e57
6062a9e315071d4cc1e582a36cc90e8b
3625ef5088c965b7684d429c0200daef
0c0de09b42bf2d54b04912c9bf635515
ccf99ee92991020228083dd81fa4e550
256d87be88861f97f85c0e9f8e5935f0
ee060398a75b39b2a03c9add1f7978e1
f9bcddadfdb5acf9c164d867f0c745d3
f9bcddadfdb5acf9c164d867f0c745d3
e23a131210f3a730d088fe9524ccfba0
2186487f2838285a0686376d31bdbbf4
c6d822cdadf581d31cc468ebad5869a8
01a9d2cfbdc7b65a4f9e56ac9842c2b1
299a1aa910c5e3f5853ebc4d95df39c3
d6ab8077608f5bf6ed64e735ff17f1ec
fb58f86d024e5aa4c7d33752428997aa
c350c71a1567b63b24a5bbfc6224c14f
cb7d46f2edbb05fdc2d46c12e6167714,4f9f8560ca8387df8e16f31ab4ef7571
b896fec03441019f564909b07db0b3d6
bf33cbc2370274877342e745f8f8dcc8
ed49e9c4c6a3f1169175a50ce27cc183
a30d42b1b088c84c2da2ce16fca5b798
e14f9a25c81fea04d919ff1d15acc569
7470b8a980304ad11e96195881a5625c
47fa65303a3527559a8f4524365a5c3c
7e882795e09328458c852abe7acfd87b
80ea838bd21ddc44585db6b08c3e8d82
527cf752f6a0030b3347f0a02f9c8ba8
dcd815cb3dbd401112ab1a91fa9ef3a0
03163195705609d1cd687ab4625aefc0
8f076ef293394c777de8d5c4fc3240ad
8d83428976f483e5e92673151f336c6e
4968949809058c41ca58ea531792dafb
6062a9e315071d4cc1e582a36cc90e8b
8a8e65ab8509f439685567d40ea9fa0d
add9d2ecffc679c3b016dbaa35398357
7abd4e2f75b243a853a8636973402439
aecb5c9cf10ec6d43cf1377ac5f5c728
ad32188ad826593f20f1f27213708737
051c68bc60c123ce99f5008609efbb7d
21fbe3cae634ef91e796092bd50e14d5
db65748051ef42ca5159d4f5f675cd66
051c68bc60c123ce99f5008609efbb7d
bf3bab9f98cf513bd09ffe6e773ab8d8
7e882795e09328458c852abe7acfd87b
a7cec9cad4df1525a31bdfc0f45ae03e
887f08f575f47bef0f590c6dde16e16a
2888fc233fe52186bdd632b250526631
dcdf26f3c7f87440b56877744814cd88
119c970e7ad443c12043caa63b6fe7dc
b2e7cdbee461467dfda0f216f677b370
2dfe826e824be7748fbe6417ca946a1f
23663f672b0eb30d9400e8009c053e5f
0d9d6fa94ae5216d9bcb9052f50f96cb
1a39b5cec567da08fdd8dd0e2661d875
3e501264d29157bec119ecbeeb24de4c
03ffcfa9e4e1f871338e74271f5404b3
f805d549425c7328c40729b84606ba07
05a2c2d6e5535bdf6a24d481273872c5
4f3e930a4c098e0235e7c3beefb4519b
9ed7bd905ff8885aae62007e5860d5e1
227d508c1de10b3271147a2a70b0abe2
f75d36e5fcaaddcfeff0e05a2cf15f1d
27551bc092712a80a1dd95cc4715f910
fc792d8bb7ad8d13c97776e18c714ce0
2379b57e8ae3e630fd05fe994c20bd5c
1cf4a76a3d606a74a34ed27e0f27751c
b644630d9adb01802fdf040a4b3d3891
daee0e66771781338d9b974bac146218
05d4d580b9a9f0692acb5950783e79af
40b0229cbf83c8857e8c9e7d79bec8e9
b758b0b14bbc1e1ad613914b959275aa
b2e7cdbee461467dfda0f216f677b370
5c90775712b39468a3e22b6deee48708
f7ad1f228ae3049f9d6d2b6d6c53c035
01a9d2cfbdc7b65a4f9e56ac9842c2b1
8bd02321f3bffe00c04a663bda6fe244
f107e3729809537344a0a4531faed727
d953147cd0d4a73585e0501bde56cb68
e6cd0120d57e5060021ce8abd17edec9
816d7568acd3d436a287b53f4d8c6559
4db883d0d82be0f97e533f25e5dd1363
baff2f8123d5c6c13585237aee6cc7e9
c1873377ef35a86716e7db29fa78afab
dce725e1c5ecf28cdf26d89b0b796f8b
ccd558b0a457902007b10ffe8e43626a
001b26b67eadea666cc3a9275c676c32
4fc5d7c934dc22c284fadfdea0d6622b
efe3b79b8dfbc5534a37c67fd08e3fe0
de6707573b047f0d607c2bfac8a8b0fc
e6ce399afaea9e9f7ef02c6ddfa1855f
96e897157907bb08a6d2fbde5a26c51a
2478beac944acaad42aa81cea341e99c
b644630d9adb01802fdf040a4b3d3891
35aed298a6fe17790be0ce24a102e4b9
74d916bbe243ee0f8c06fd56801fce24
306992c1996d8083d53a0bdfea67bd34
d63fbd5f0d6ac07328e33358cb058a88
d40d704f68437bb2c4499614b45a2b73
68d0e9384068227713f7e37dfcc9d0e9
20925a2d855e8a15c1e5c48b54337c95
e14f9a25c81fea04d919ff1d15acc569
49c66e069adb221d74fb741237f007f8
e29e1dcb51131a6ea34fee85b7e6b882
7da26a6a112fc0a4853a40d34e3ddb4d
b7499b38e46510bbcb3ca3606dfc4091
81260a309f8fb7e18d5d7937a1718ddd
816b9dfafbfd91bf3d828efd5b9e46fc
6959540b348bd00932f1a0337d44ad04
8f7723a6462f1ed308efc9010d02f279
0223a393e2c3ae8bd6a39d3de882bf02
b73d8629ae2d008a8184b8761b4a9c87
00036b0d076874775f025b132626a224
a60305ce45d1bed9759420c05bb74200
fa3afefc843f28b1d2ba2780da5feb92
901a10ed899d9c02502087c7819f38ea
081c152961797040930c8128122e0e00
65066e0d171be18d92f1e601aaa36260
fbdd29796d1d0fadeb05bd0e264f5df3
3064174f44225659b464afe56a01625b
ae1cb4efb580320ac44784e5b53a5749
7abd4e2f75b243a853a8636973402439
3ca114ffea4bad23501640afaa30013c
bf3c84b69ae0c29fab3dbe8b3a9033ff
8dd81773b5d03c3f4313e80cc0f5ed0f
5a06c33950409e43f713d56f70f1b303
482e65f984de1d07b79b1ab35f7e7cb4
9612ba0b6726e0945ffd43aa4c59c8a5
ad32188ad826593f20f1f27213708737
7f9159a0d78aac2a2a88e312e4448a32
f9c0d1a6c3dea3aa02042972502d6a5e
013964144ca0a275fdccb11561d23fa1
7d2eb6fc914780401932798a3c8a66d5
ddfd36cbf7eec6cd62016fb8608a51ce
ccf99ee92991020228083dd81fa4e550
e14f9a25c81fea04d919ff1d15acc569
ccf99ee92991020228083dd81fa4e550
fd1c283728ced59db32ac882c2ac1c97
3a91a445ab0b14de66d30c0b7ddc89ca
8a8e65ab8509f439685567d40ea9fa0d
21fbe3cae634ef91e796092bd50e14d5
f732cd2547622a112d7cf896c67a9ab2
ae5c3471f12387be2adebc7922067ff0
3a91a445ab0b14de66d30c0b7ddc89ca
ccf99ee92991020228083dd81fa4e550
3625ef5088c965b7684d429c0200daef
96e897157907bb08a6d2fbde5a26c51a
2379b57e8ae3e630fd05fe994c20bd5c
ed648db5c82e86772c1c3f76fb2c42e2
d2e9271fd4a4a1a79a9cbbeee4f4a5e1
0d7fd55c853edf44fd716f2e5eab72da
948c612f0e8393bee48d6ec07b10973c
8d05dbcb455bad71178026daea864db4
70140e89c67019a069783f7a71559bc0
3307c3550d086d6f8d06b8a85bc39989
ccd558b0a457902007b10ffe8e43626a
b881f5f8dc378d3049d1b9720e10e063
1ac1818c94bdcbfbefc0f582a0b25136,f20c1b43cb9ce21b83778e28fa70801e
b33ad589799efe4f0ae9a5bb57c2c734
bfc7954327958deb552352afc9e337c8
efe3b79b8dfbc5534a37c67fd08e3fe0
2d71e464e127d071054f66bc966a2aaf
1e22dbbe4fb47a2c712410793836be00
b09a79d6ad6b026bef05c78645335902
f84846d7ac6bc61b326ad880cbf28acf
c5720d79367be461bb5ddc9cc12d879d
911d574eedc431afdce205b6a5a0095a
ccf99ee92991020228083dd81fa4e550
b2e7cdbee461467dfda0f216f677b370
bb71b3cee023a640cba5c7176f5697cc
13087819ac1f0570a175896286155ef6
6959540b348bd00932f1a0337d44ad04
9e248f56b5297c75edb4ad937b82c1fe
daee0e66771781338d9b974bac146218
ccf99ee92991020228083dd81fa4e550
289b8b2fdc152c17d589997c58aa3d98
53198831c219ac4fb6916145a41a94cf
169365f1873a0855b7acd5c59a8fb994
e86e11d6310bd20eade2c7de37b6595a
3b053db0cce295cc9dfd6848c1f766d5
939f2baf99db127e01ec6fbde100de5a
70e566a092167f5ee4fdccaea4af6252
7e4f83129707754f57b6d7de87712a63
f44422bd25e349884ea5b151708d4168
ddfd36cbf7eec6cd62016fb8608a51ce
fd1c283728ced59db32ac882c2ac1c97
eb89b214cbe983a4470f97aa0c4b4bcd
a81d5716b461240ff91eb40eb99a0768
bf3c84b69ae0c29fab3dbe8b3a9033ff
6895f435135caa336e0b63b1ff1eeb68
ce692dd8417c8e34746156ce9b799e91
05a2c2d6e5535bdf6a24d481273872c5
e2555e80b296186557426f4a05012d3c
16baf76a47b2c3183210939f73a345ee
78ca76476c7f9ce79c4c0f4d63f80803
e280f8f908ed6232649d7275c4f3c263
fd1c283728ced59db32ac882c2ac1c97
849a9f9616379cb2f2b6b4f639d30808
687f704d25a29f23c2dbf2a0b2d2dd78
7eb3bb889d4a222e1d44d85cfb488b73
c5720d79367be461bb5ddc9cc12d879d
2e493bb63e94c96bed31ece791476c53
8f7723a6462f1ed308efc9010d02f279
db44fc95101c2e96c74843de12819506
66a83e45f28f5609f6dc6f9bc0724d06
d6ab8077608f5bf6ed64e735ff17f1ec
54497a230f6a4fc29eda3e81a537ac11
6759e65c8ea397c3fda1a40313b00ff8
40b0229cbf83c8857e8c9e7d79bec8e9,dd416340a4613c46ed12b87717e4a8ac,6f9ef114e4478a961bf3e59d6441f243,4e953a9700fc3a4de58eb3b066eb4c74,a0a5dff287d5f43498a81934df34f6e1
fbdd29796d1d0fadeb05bd0e264f5df3
507b57e6d8e48d9df805e58817034fd1
5ef139e5e983b02ed0f3fd3d095b1eab
840a7401e8c21746ee95729fda82d540
8cfbdabb841dfef12e3e7d25a29a2d1d
92698f95c3f6fad49f138d3a500b24c1
426dbfb07393dab2ca6440d4afff6c25
a04fc54f775f2776321673d69c80d4ea
941095c6f1ea8aa7f2db35cd15d4526d
93ebd7da27d17b67cc9a82404a0765d2
0e832897fa736c9a232552dcecfa36f1
34c0788322a9be310b1ee2ef24da081d
f5d256fda01b89f2952ac64ac7cbe846
948c612f0e8393bee48d6ec07b10973c
169365f1873a0855b7acd5c59a8fb994
c9d44105b828c6f72ec5db6d47b8b7b3
36c76df229d308d1d3267b3092398872
a1c3759c68f6d088d5e6fc8bef76e739
a1bd88629f25c42bd362429ab5c81361
2f6f1c08abdb82753f1635b8bb22b318
c92f34dc31db156f4cd691feb313a19f
b59706cad5c7c00a4b7316526096bd09
380cea06f23efbb3f9fcd735cb7656e1
9ed539a96c6ffd96f54f63c13fb1e0df
f6951cefbe653efb7a0fcf3ae0885d11
16f289b12124693df4f5177fb8bcadef
f38a2fe99994feb158aa4a165cca1e64
63eac6241c9214367823d0059600e423
0e0c96f2cf41b938cca9852efb6a3393
a74029be428eb715469c37c5c087051d
901a10ed899d9c02502087c7819f38ea
b644630d9adb01802fdf040a4b3d3891
1b9d847e265df28ae80d2c4b3a8b2901
458805b20fa284b8076ed65b0dd04335
d897960d3da4f72ee5dd1425972f479f
b57508a80ba85a740080aa172b5d60b1
5480d2bfd771ffcd060f512849da42c4
33045b4ebee6dc59791628ac86531c86
a81d5716b461240ff91eb40eb99a0768
37b95887f746d30625bd38d8a1589c7e
107a1659879414884064e305372c5631
18d01ec07210c571629cfe9d55b98026
3d2b57725175988984cb434333920afd
4c8ba0bbff80ab81c5084f11a2549827
4f9f8560ca8387df8e16f31ab4ef7571
677ee59fb5726818d18024fc01dd6bce
b2e7cdbee461467dfda0f216f677b370
731481a51f92ca1165fd56cc07a85bb9
45add99671a0f66b8d2b7098f89fc72c
c6b56eade24f7a81fb4e3e7f92c27b47
0d9d6fa94ae5216d9bcb9052f50f96cb
2c1505e613c7a9861bd2d8e17a996ad0
1f29f7f1b5af1d165f33e5da794bec26
686d923dcaddb8bc472129cea202ece5
aefda5b55ebb20af07751f2d7373de46
306992c1996d8083d53a0bdfea67bd34
6d0cd68ed8878927cf202b140f1d43c9
677ee59fb5726818d18024fc01dd6bce
e103d09f895b97f45c376a60b2c56151
05a2c2d6e5535bdf6a24d481273872c5
f7ad1f228ae3049f9d6d2b6d6c53c035
daee0e66771781338d9b974bac146218
f16a381e577c5ea74b5e2c02a6e64a58
fdfbc6c05521ff446e9d20449213284a
f08b12a6e95cf6163c524ef687d61fff
4d523f16d2ae428ae4189bdf8681fa10
2acd298ef2c554aa58ea72759ffb5531
f5b37c482583796b56e43bd8f5724b9b
1b9d847e265df28ae80d2c4b3a8b2901
173920288064a7bf27bcc654eb63323c
d24dec1f4eaa71f4cd40c6f2ff2f8c4c
1e6efa73875ae5b85c8874c7e6c11f4d
507362674ccf915721cfc5d80027956d
279d1f9de9e50356e48457ae34e25e27
cde35f01dcc2e3b6fb1aca36ae0ee237
2f6f1c08abdb82753f1635b8bb22b318
89143c5189252c885169a7f7ea20e10b
963c824e0b07a3f98f301e3e7cd442ee
c843f95b066d1e84cf5be5e354efebd7
16f289b12124693df4f5177fb8bcadef
5cd3ceb7c0ef7b92a7c07f1205565d55
6767a7ed15098325f2580247363793dc
991844d4a0b1784c89f14f0c2c9cd19f
f75d36e5fcaaddcfeff0e05a2cf15f1d
793acae5d364d1ed2156f56b7702ded9
3aef2dc723538f03b26af98c33258669
c5720d79367be461bb5ddc9cc12d879d
a30d42b1b088c84c2da2ce16fca5b798
16baf76a47b2c3183210939f73a345ee
abd6ebbf2a002a1b194630daecdbd2d4
84a89358c67cfbd28163d67eea589c27
eb158e420f553716a872ad93cc0ab002
cbd465702d40fa7da1cbf835d7530029
15a89725f831a8cd0e0594c82f2afc91
cbbcb70943244bc738c5c1c0040f835a
d6ab8077608f5bf6ed64e735ff17f1ec
637ef19ad1a589d4a570ec593a7a34a5
9723f55e165766df638601db2c550e17
3b053db0cce295cc9dfd6848c1f766d5
3fd7d892b0ada9cf0f7c7ce963bec157
672403cdad2280c224c48a86781ec78d
281f658f4f680aded3baefa9d1512146
3625ef5088c965b7684d429c0200daef
d40d704f68437bb2c4499614b45a2b73
8bd02321f3bffe00c04a663bda6fe244
f7ad1f228ae3049f9d6d2b6d6c53c035
cb58e48b611cdedea041a63e53b3d600
50047e4b380dda5f41ba9f99fd557df9
23663f672b0eb30d9400e8009c053e5f
72cb8cb9d32d604d1863c8fa76a7bcfa
4fc5d7c934dc22c284fadfdea0d6622b
cacd5b8ed67e9e94a289de0ac25a8ea5
a1fe35eb510f9f68846fa704c2ac3c8f
1952a815e289a25396905fbe8f29f671
f10a8e559deb772c2b8b8f547e38b21e
fb58f86d024e5aa4c7d33752428997aa
dc71ab56ab5e0075a7edf3b6af248022
97fcd09c8748af89252a66ae63686ee1
d3af2d890b6c1331abc0cf1bab1b66e4
b995567c39f8f378112456f0b1594c86
5e5903ca525b51c4e1ca692e523d9af5
5e342630b24ba50178896af11e67655c
bfc7954327958deb552352afc9e337c8
f9c0d1a6c3dea3aa02042972502d6a5e
1bf141bf3e9985c89769c6d16c1cbfbc
f10a8e559deb772c2b8b8f547e38b21e
639c075557bb940cfa7e6cb90f1d7dfb
a1d469adbf3bd0adc4379131d52b4379
3a91a445ab0b14de66d30c0b7ddc89ca
b2f82c344a844898d26953f64df2ff83
527cf752f6a0030b3347f0a02f9c8ba8
1e08e6e08db81f79daa1b2c6f3081d75
e049fd711a582a90c5b9e73f4464d4f1
03ffcfa9e4e1f871338e74271f5404b3
27f5d5b8b4e2bac9a44cb4e4652b471c
f96c0e7252688bf0b362e95c7dc55542
9a7ed6b4667075503f2c3ee97cbf29d1
93da6de45bac6556d559e27278cb6e54
9398961707509100fac0c849a6b3d5d7
5c155bc8acd3d13da786a373040a240e
45ce9f6602073c6df14af4c53f61b484
fca1f2a2526124de979f3c15a53bc084
8cfbdabb841dfef12e3e7d25a29a2d1d
8d83428976f483e5e92673151f336c6e
d7ddb097e2138e1c72563b6ccb2af019
b2ef9941ccb75ad33ad5902e97f307bd
289b8b2fdc152c17d589997c58aa3d98
0223a393e2c3ae8bd6a39d3de882bf02
41714dc8efa72523fa91c4061ed0ced6
6f9ef114e4478a961bf3e59d6441f243,4e953a9700fc3a4de58eb3b066eb4c74,6d7e042a000deca140c330ab99896ebd
f375fcfa1a0d974c2792f50a9439fd09
dcdf26f3c7f87440b56877744814cd88
6e280b80646b36652853802041e84447
aa32806dcb51596555489e93f4c4340f
507b57e6d8e48d9df805e58817034fd1
c9a9ecf56ee8b676d05588d2919232cd
f20c1b43cb9ce21b83778e28fa70801e
25c2dd2b9807a563dd4b01772a41f685
087b12962dc0b886736fbe861fcb7f16
0038f2c6b857ba9e169bc6e31a37e86a
a81d5716b461240ff91eb40eb99a0768
bad451268583315c8689ea4e737b6c26
fe1ee42973d48bc63fbee3c6d9f78160
d190cc378aabcfdad876818bfd92a118
6f9ef114e4478a961bf3e59d6441f243
352d194baed18d1ace514dd0d01fa63f
586db98defc0129ea0f7f11f4917bf04
308285789caba675b139eb73d40bab4f
05f86807792bc5668f250749a1c52bda
bcd183c6dcdb056c8a0180703f9824c5
ca5b0b284a41f95cc7684e3e791e5e43
f75d36e5fcaaddcfeff0e05a2cf15f1d
35bde7180b6ead5f026789cdc84fa8a6
4af09d7b7425eac4d29b2a817902f4d8
77fd740e226dd625f8b98f91ef202eb6
854c96d3f08e9a639c50b0b06ff2ad66
ec826b4a85aec5221c8d6510f1dc7927
d24dec1f4eaa71f4cd40c6f2ff2f8c4c
872105665564640e3dbb2d9a24f5ced1
1f29f7f1b5af1d165f33e5da794bec26
eb158e420f553716a872ad93cc0ab002
3700221b76918b09c41c38ab7ca0d80a
157d68a0e73262e443ad843e7d29195f,4f312b0f37bf9d86333114a4f467ddc3
f107e3729809537344a0a4531faed727
3c4251078c1b4f76813c5c66da0e66d2
695a6f4d2a019add2c2ea22bfbb3a9e2
4c8b5256d902115c72953d55d9a77667
80c33a887cb058f204da9025d782b815
92ebe5f3368b52fa143ab6a1b25d9b09
bc154087659431c11af968bbc165f79e
87ec28e9555f4f5ecbf0a2ac91fa0e75
3442cebc305fbdc04afd63d9e4938a57
abd6ebbf2a002a1b194630daecdbd2d4
507362674ccf915721cfc5d80027956d
a1fe35eb510f9f68846fa704c2ac3c8f
75043c96c729a77d1c7d40d326cc75b4
31ab065a25a21564223a898cd741e2f5
2e5ef6887eca86d5eeaac00e40d564aa
3eb167d5ba1a709b3728fadc859f2dc9
70140e89c67019a069783f7a71559bc0
ef280f9608bfc2c73cc1f238db25060a
4d523f16d2ae428ae4189bdf8681fa10
2ef791a0727170fed776315c599cc310
98b6a6f49e75a1c7367ef6358fc8107b
4e8ea8316ec0888726c2a43d5337da63
265152567ab5b818adf0ce68801b8fa2
6ee4478c0e343d03a10f3355dcf9f4d4
0271e16d9cf6af3616c7f5646f1ed64b
bf33cbc2370274877342e745f8f8dcc8
9a5205d8ef4e61e65d574a8b168a9c2d
bac6597d8d6c0ca72075c462c4d17363
7606abf8f18a7e1894ac806623502a8c
889e1f826bc1ffa8c58fd538724ee218
161c299ee26046641e7ab7453642e631
b5e720842c2c1b3fb3c71309fa4434bc
6959540b348bd00932f1a0337d44ad04
4d523f16d2ae428ae4189bdf8681fa10
27f5d5b8b4e2bac9a44cb4e4652b471c
36c76df229d308d1d3267b3092398872
eb158e420f553716a872ad93cc0ab002
849a9f9616379cb2f2b6b4f639d30808
3f06d1ef6780bb1a6f4c52417dbe8d0e
3da304722fa16d03f50a47000f7ae920
9c932c2d18ae74132d3225a6214b4bae
f5d256fda01b89f2952ac64ac7cbe846
e103d09f895b97f45c376a60b2c56151
ee1f14b3efbe3786f4c2ea50ca93c950
643fb24bd380e2f181c3a958dd465591
d2e9271fd4a4a1a79a9cbbeee4f4a5e1
7b6a1ef444427e2de4568a1d78f1910c
e22df26ec5200ae93010595f0677c1a6
363abace285483d5015d3d044b5bc101
2aa5b0d0ace3a1542fba29464ce7f21e
7c5f3d7109a088df904321d3d6eb649a
cde35f01dcc2e3b6fb1aca36ae0ee237
f732cd2547622a112d7cf896c67a9ab2
bf33cbc2370274877342e745f8f8dcc8
a9df6c8208e4ca184b689d42b99ea1cb
2a630a08a4f592215e5f0661960aabf5
f75d36e5fcaaddcfeff0e05a2cf15f1d
50047e4b380dda5f41ba9f99fd557df9
840a7401e8c21746ee95729fda82d540
03ffcfa9e4e1f871338e74271f5404b3
45ce9f6602073c6df14af4c53f61b484
922594eb52879d4627845a02df136f12
bba63cbc3e68d767fe13e3e609f0d7b7
b5b9efebcb34dcab469ac4ec2e3e00da
f84846d7ac6bc61b326ad880cbf28acf
5e793aac5bf49d8e56924c19e00e659e
b26b42fa48cc68886ca0018d9893fcb5
f9bcddadfdb5acf9c164d867f0c745d3
d08912a6eb92812348a55698010f3871
cc634c526fe4da575eac6077a3071644
b995567c39f8f378112456f0b1594c86
33045b4ebee6dc59791628ac86531c86
9a5205d8ef4e61e65d574a8b168a9c2d
4c8b5256d902115c72953d55d9a77667
533b5e2cbe8affcb7c84842da6a10a81
66a83e45f28f5609f6dc6f9bc0724d06
90d2a26e0963b293fefd214569d17cfb
77fd740e226dd625f8b98f91ef202eb6
f9bcddadfdb5acf9c164d867f0c745d3
60dec45d8b4bbda8681e85f05e979f95
e049fd711a582a90c5b9e73f4464d4f1
70160d24b2e92217a49cee2e908fcdf2
d3af2d890b6c1331abc0cf1bab1b66e4
bc00cf32fdfe9944f7b4b92ad9596035
b51aec0cfcf0eecbaf583f913cc18f3b
2a630a08a4f592215e5f0661960aabf5
165388c7ec7fa6e5462d4a1c8df48d8b
9e72c3298677eb33974cb7e92ef0a6b7
0c2126a38c0ed90c78862f4d35c122a9
75043c96c729a77d1c7d40d326cc75b4
00036b0d076874775f025b132626a224
021c070c1f6250468fa9caf0eae5c2ff
fd11c037678755346d5d87939e8121ad
96e897157907bb08a6d2fbde5a26c51a
9366d77a7b7a2fc5c33d1a02ea8a82da
aefda5b55ebb20af07751f2d7373de46
714e124d2cbae5e408b52aa9c65d61b2
50047e4b380dda5f41ba9f99fd557df9
b59706cad5c7c00a4b7316526096bd09
cf3c57ea59d001362293960a88f112b1
06efd45528199414f37602fc26b1e5a2
256d87be88861f97f85c0e9f8e5935f0
3eb167d5ba1a709b3728fadc859f2dc9
380cea06f23efbb3f9fcd735cb7656e1
8a2c67da95795be7b01b0ea588f19c51
8812b05556753b1ed2a2f439baddfcd1
baff2f8123d5c6c13585237aee6cc7e9
4d3cdd247fca8f3aacf2d50ea19faab2
559a27d0f30ea0b131cea62ab9546c86
6394940445dd407a39da9df310337b7d
793acae5d364d1ed2156f56b7702ded9
157d68a0e73262e443ad843e7d29195f
18d01ec07210c571629cfe9d55b98026
fc5de224caaa5ccfa9abce15370fc950
66710a5755b499660b59a3c875cff124
df1733992db1b4645207a5b06a1f953a
87ec28e9555f4f5ecbf0a2ac91fa0e75
d5835f133f559870443026042f3315a2
ae45d1c21e9f38f3dc08d859f503f09a
1a39b5cec567da08fdd8dd0e2661d875
11990aee734595455a6fcfe54eb92205
74d916bbe243ee0f8c06fd56801fce24
70140e89c67019a069783f7a71559bc0
8cfbdabb841dfef12e3e7d25a29a2d1d
4eb3b5c306bb256a34ccab6bed0af879
4f3e930a4c098e0235e7c3beefb4519b
49d1b669f1408f5495fc342e5a367165
92ebe5f3368b52fa143ab6a1b25d9b09
8543f999bfcf05ee885408f70d7a87bb
3307c3550d086d6f8d06b8a85bc39989
35440f661f1ad24b3bc9ccd845ab1036
cbd465702d40fa7da1cbf835d7530029
1bf141bf3e9985c89769c6d16c1cbfbc
2888fc233fe52186bdd632b250526631
a81d5716b461240ff91eb40eb99a0768
de6707573b047f0d607c2bfac8a8b0fc
b8e635be69e7ef8295f38fe9147a9d9d
a0ee6406194f05b6e21a3b3930dd1eac
f34424d3f47c5f6d60e146589e3e7e20
c521a7d8077f759012c14c6bfb531cbb
0ed3ab81f348ee25c87f92ab4087ec5e
56b28258fb8ccdbf1f5d4801346a47ca
f08b12a6e95cf6163c524ef687d61fff
d40d704f68437bb2c4499614b45a2b73
fa3afefc843f28b1d2ba2780da5feb92
4bfaa99566f1f39a2986e859562f18c1
e8bb78b1dffdfe27d544fcf9228b5b7f
35ce84e828c308566b763a7a21450245
902d1160aeb6b79c0084415871d8aa96
d24dec1f4eaa71f4cd40c6f2ff2f8c4c
cf3c57ea59d001362293960a88f112b1
426dbfb07393dab2ca6440d4afff6c25
3b053db0cce295cc9dfd6848c1f766d5
c350c71a1567b63b24a5bbfc6224c14f
50fd1fbccb1aa184e8cc9353207005c0
533b5e2cbe8affcb7c84842da6a10a81
a7dc01d775e22a34c4caf0cc9bc90273
cbbcb70943244bc738c5c1c0040f835a
5dbe282f688ec08e9f7f0803cbefc372
4f9f8560ca8387df8e16f31ab4ef7571
b51aec0cfcf0eecbaf583f913cc18f3b
b995567c39f8f378112456f0b1594c86
b486e4c64373befe35c0dd65be80e1b1
1e6efa73875ae5b85c8874c7e6c11f4d
6033b7f65f269e4f50b97e9fd4d470b8
7527d548c66497d1ab33fc17bcd2b9b8
dc71ab56ab5e0075a7edf3b6af248022
31ab065a25a21564223a898cd741e2f5
ea84fb80acfa95bb725afad25ce26baf
c63a50793c8bc85164ca67185bbd5ce9
261ae85a599bcdbb534339e386445430
5ef139e5e983b02ed0f3fd3d095b1eab
13087819ac1f0570a175896286155ef6
353093ebf7e589f08444bd296fa44e97
4e8ea8316ec0888726c2a43d5337da63
639c075557bb940cfa7e6cb90f1d7dfb
6033b7f65f269e4f50b97e9fd4d470b8
37a51512676179c4e60df9851cfe03d3
490f654e05b4b26c5c78176d11230540
a1fe35eb510f9f68846fa704c2ac3c8f
a60305ce45d1bed9759420c05bb74200
51d345811357ecfeb79ba814e56d4fc3
53e0a337dab988e3ff85d0fb6f5e8dbd
d5835f133f559870443026042f3315a2
edcb078fc1456b07dfdc1cf90c44e3e1
13bd89481a54c506f4f16cfe1e139d25
e84fb53e9aa65d7b24f6da448ef66c4f
7e33f2219c42f466b48669da84287ee9
dce725e1c5ecf28cdf26d89b0b796f8b
0c444905ab9af6e79e7e25ba218eed36
3a91a445ab0b14de66d30c0b7ddc89ca
948c612f0e8393bee48d6ec07b10973c
2f6f1c08abdb82753f1635b8bb22b318
ee060398a75b39b2a03c9add1f7978e1
bb7c0faa9029b682b32e0997f3cc7b70
fdfbc6c05521ff446e9d20449213284a
9ed7bd905ff8885aae62007e5860d5e1
a7cec9cad4df1525a31bdfc0f45ae03e
f068075227855de709cd7bea20b94712
533b5e2cbe8affcb7c84842da6a10a81
849a9f9616379cb2f2b6b4f639d30808
c40990246bd03c18ef187a6bd514d464
f375fcfa1a0d974c2792f50a9439fd09
6759e65c8ea397c3fda1a40313b00ff8
ee060398a75b39b2a03c9add1f7978e1
9c932c2d18ae74132d3225a6214b4bae
dd416340a4613c46ed12b87717e4a8ac
ebefb82e4d8e381f2cb9a635b45dd9af
682268b74cf72bef28b3a2b697524f64
add9d2ecffc679c3b016dbaa35398357
e88457aa452f777eef85fbbfd95ec85e
63eac6241c9214367823d0059600e423
4af09d7b7425eac4d29b2a817902f4d8
0414b25537824df6303343bf8a0bce76
9a5205d8ef4e61e65d574a8b168a9c2d
051c68bc60c123ce99f5008609efbb7d
03163195705609d1cd687ab4625aefc0
a1c469d02bf1c38afb04a490e89db776
41714dc8efa72523fa91c4061ed0ced6
d03a1d460db0681e17d2fee4cd66335d
686d923dcaddb8bc472129cea202ece5
aecb5c9cf10ec6d43cf1377ac5f5c728
e5aa65b4162a6c0b5f39dd20f8a53e83
c9d44105b828c6f72ec5db6d47b8b7b3
1e08e6e08db81f79daa1b2c6f3081d75
6ee4478c0e343d03a10f3355dcf9f4d4
a30d42b1b088c84c2da2ce16fca5b798
72b705952c8dc1538c2e7611b9e731e8
bb71b3cee023a640cba5c7176f5697cc
507362674ccf915721cfc5d80027956d
4968949809058c41ca58ea531792dafb
0c5fe72a6de028fd69d82ec673b761d2
051c68bc60c123ce99f5008609efbb7d
63eac6241c9214367823d0059600e423
81260a309f8fb7e18d5d7937a1718ddd
35aed298a6fe17790be0ce24a102e4b9
4b0b15db52831c57ce89a363299c6861
5be77ba5aa6a1d99f764ad6356ad4d52
0223a393e2c3ae8bd6a39d3de882bf02
8cfbdabb841dfef12e3e7d25a29a2d1d
9937b8d3200640feb7666f6e57aa48d4
3e9eacd0722f65d9b33f3b4367f01b49
db1c55573becfbee3903ae573224b179
4e9a55218ec14c55f9e9acaba510e6fb
7cc6000de2268586c1221ee6a1efee37
70140e89c67019a069783f7a71559bc0
127e8b69619faf7c18e0da6c7ba9bd5b
e049fd711a582a90c5b9e73f4464d4f1
7c960ceb395435846ac66ea3086c970d
021c070c1f6250468fa9caf0eae5c2ff
eeb94f7eb6bace26301d5aa1ebcab163
a1385619e5caccf4b3b83d393c81642d
0c444905ab9af6e79e7e25ba218eed36
74d916bbe243ee0f8c06fd56801fce24
73ad0ff1e72011b6c9c07f19a8c4f09e
fca1f2a2526124de979f3c15a53bc084
baca875e1c185711a26e02177ae10a5d
2c311bc8069feeecfd14d70897dc0877
b31953accf1e2c2c03a21e525ed12afb
a9b822be6e43936173779e3641cccf37
686d923dcaddb8bc472129cea202ece5
5dbe282f688ec08e9f7f0803cbefc372
ad32188ad826593f20f1f27213708737
57b5f4e5596390b72b76687fb49a04a5
b788a1dc78950ebceef7adb6ff5ff49b
154392ec995e88a7fc95e4cce6af9fb2
dc9182ae415b862068cc47750965de96
d967e2a9d2e8cdfa87e7f635136f8112
cbd465702d40fa7da1cbf835d7530029
35440f661f1ad24b3bc9ccd845ab1036
9c932c2d18ae74132d3225a6214b4bae
e1b7b88ad76d7480beb24c0e489e3034
afe72d2ef971f6330b38c9f1ab219910
8dd81773b5d03c3f4313e80cc0f5ed0f
e8bb78b1dffdfe27d544fcf9228b5b7f
542bfb8262044fbb1bb33ce9d3793080
bb71b3cee023a640cba5c7176f5697cc
f8d344bb4d8c6d9ecfad6577f56d5678
2b5ebea49fd1a7a8a8b94a10d25f0ec5
afe72d2ef971f6330b38c9f1ab219910
25c2dd2b9807a563dd4b01772a41f685
695a6f4d2a019add2c2ea22bfbb3a9e2
911d574eedc431afdce205b6a5a0095a
bfc7954327958deb552352afc9e337c8
4d3cdd247fca8f3aacf2d50ea19faab2
70140e89c67019a069783f7a71559bc0
714e124d2cbae5e408b52aa9c65d61b2
8f0626f20824a22fb383950427bfdf1d
f62e8250143a61e087015b0677894932
311cf3a64ca7218c6c6eb7e9bdd18782
4af09d7b7425eac4d29b2a817902f4d8
b26ea9cb75c69197895f8e9c9aa819c8
80c33a887cb058f204da9025d782b815
cb58e48b611cdedea041a63e53b3d600
261ae85a599bcdbb534339e386445430
c5d0e8298c8231faacf37c39d418d250
edcb078fc1456b07dfdc1cf90c44e3e1
a1c3759c68f6d088d5e6fc8bef76e739
5a06c33950409e43f713d56f70f1b303
984809425e10ef00c06559d5faba96c1
6639d0ba46faea4e76013e7956eb4497
35961793c02f21072b2af72e769af5f1
381d2f41181f2158b793fc546e9a4a2b
b3f3a8609446e2af6513baef5f7ba8fa
ed49e9c4c6a3f1169175a50ce27cc183
527cf752f6a0030b3347f0a02f9c8ba8
ed648db5c82e86772c1c3f76fb2c42e2
69c03212aced107aa6a570d62cddf377
0c5fe72a6de028fd69d82ec673b761d2
dc9182ae415b862068cc47750965de96
6639d0ba46faea4e76013e7956eb4497
cf3c57ea59d001362293960a88f112b1
0459580538600b2c4ff56fbc2dda3f8d
e84fb53e9aa65d7b24f6da448ef66c4f
a63caf3220978f6f673292f79a493e7a
507362674ccf915721cfc5d80027956d
b5e720842c2c1b3fb3c71309fa4434bc
6ee4478c0e343d03a10f3355dcf9f4d4
8e4d39a1e12d173da83ba92224917e76
e86e11d6310bd20eade2c7de37b6595a
c6b56eade24f7a81fb4e3e7f92c27b47
2186487f2838285a0686376d31bdbbf4
9d5e7952ff3ecce46cf7a6a76837e51a
29e5faf44e37519ab55b95e5b4b87d21
281f658f4f680aded3baefa9d1512146
66a83e45f28f5609f6dc6f9bc0724d06
0c2126a38c0ed90c78862f4d35c122a9
cacd5b8ed67e9e94a289de0ac25a8ea5
bfc7954327958deb552352afc9e337c8
0cbd2d21319244a40e32a82d6e227afe
05d4d580b9a9f0692acb5950783e79af
165388c7ec7fa6e5462d4a1c8df48d8b
a7dc01d775e22a34c4caf0cc9bc90273
bba63cbc3e68d767fe13e3e609f0d7b7
4b0b15db52831c57ce89a363299c6861
b3a19fd58ad492f377431c4000e947b1
bcfa63831c099ac7ad457e7b30471635
939f2baf99db127e01ec6fbde100de5a
7b6a1ef444427e2de4568a1d78f1910c
9937b8d3200640feb7666f6e57aa48d4
e45f7c307e67b13f457504ce1e93adc4
ca5b0b284a41f95cc7684e3e791e5e43
a9b822be6e43936173779e3641cccf37
051c68bc60c123ce99f5008609efbb7d
5480d2bfd771ffcd060f512849da42c4
0da3cbbdbf7158b0981ee29b3d686ca6
ccd558b0a457902007b10ffe8e43626a
bc00cf32fdfe9944f7b4b92ad9596035
acaa67e0837a1c506b4ee33778c3d34d
70e566a092167f5ee4fdccaea4af6252
9e248f56b5297c75edb4ad937b82c1fe
b486e4c64373befe35c0dd65be80e1b1
d79f1283e52a2c0ccf82c9516153f8cf
b8e635be69e7ef8295f38fe9147a9d9d
887f08f575f47bef0f590c6dde16e16a
fdfbc6c05521ff446e9d20449213284a
490f654e05b4b26c5c78176d11230540
7b6a1ef444427e2de4568a1d78f1910c
c022301d3e96a8b59a0370c57d285f34
388a5a3fc874395eaa19dc989099e872
391c2ea7ba645d4107db89ac008ad908
7470b8a980304ad11e96195881a5625c
afc11567288caf51db32557dfe1cf238
021c070c1f6250468fa9caf0eae5c2ff
03ffcfa9e4e1f871338e74271f5404b3
0e0c96f2cf41b938cca9852efb6a3393
db65748051ef42ca5159d4f5f675cd66
ee060398a75b39b2a03c9add1f7978e1
3f06d1ef6780bb1a6f4c52417dbe8d0e
b758b0b14bbc1e1ad613914b959275aa
cf5f59646b9ee163bbb9c5bf55e7e39e
a81d5716b461240ff91eb40eb99a0768
a2469be912c6cb69aecde7af497c5524,6d7e042a000deca140c330ab99896ebd
7b4b0209baeb1fed155051b6f8dbfc58
161c299ee26046641e7ab7453642e631
aa32806dcb51596555489e93f4c4340f
21fbe3cae634ef91e796092bd50e14d5
db1c55573becfbee3903ae573224b179
8a7ab1f90a61bc0baca9c1b02c2b88d9
0c2126a38c0ed90c78862f4d35c122a9
4d3cdd247fca8f3aacf2d50ea19faab2
c942b22440dfbbf083726d8b843ab2bb
57b5f4e5596390b72b76687fb49a04a5
e46289d37fa76918074ed8119f65a5f2
38ab3499c5cf480879f7cf34567f24c0
2186487f2838285a0686376d31bdbbf4
48e215170f43f1717d978f0fd56a92fa
959c47552fda50d8cd039f60be32e643
4b0b15db52831c57ce89a363299c6861
299a1aa910c5e3f5853ebc4d95df39c3
b26ea9cb75c69197895f8e9c9aa819c8
edaef13be77ad2a413af6bb4498b1ccd
68d0e9384068227713f7e37dfcc9d0e9
4d9ed289a439c416bb1619a3b408930d
ed49e9c4c6a3f1169175a50ce27cc183
47fa65303a3527559a8f4524365a5c3c
887f08f575f47bef0f590c6dde16e16a
5be77ba5aa6a1d99f764ad6356ad4d52
03ffcfa9e4e1f871338e74271f5404b3
9366d77a7b7a2fc5c33d1a02ea8a82da
051c68bc60c123ce99f5008609efbb7d
c40990246bd03c18ef187a6bd514d464
6033b7f65f269e4f50b97e9fd4d470b8
8f0626f20824a22fb383950427bfdf1d
7a039abc3278bd040255b3b020b8a305
f805d549425c7328c40729b84606ba07
7bdc8844e34db81fdde25d0ce438b6d8
4f31add4cfefcf37ff18121282aa9b7b
cf5f59646b9ee163bbb9c5bf55e7e39e
ee079757ecd9b7c73e31920c6cd4067f
f35b403a015f03b9f4a7abad0ba7c291
7084eeff99226c4eb5d759ed96990352
503a979ce10f2ec8b7ee25871f90e010
f44422bd25e349884ea5b151708d4168
7dd54d51073cbbe27a638c1e77e0c87a
013964144ca0a275fdccb11561d23fa1
db1c55573becfbee3903ae573224b179
60c7819938d980c38e8cea68a6049afa
a1c3759c68f6d088d5e6fc8bef76e739
3e8502bf992392fb9413a868521f6aaf
878ffeff84f1422cc50ee869bbc236bb
a4c2d4207408f14b4ffdacae20ca08f7
686d923dcaddb8bc472129cea202ece5
d192e8eca0b215e58fc76ed5e7cdb8d3
3fce16d0d5d0004263f8f15e3023b50b
49e5abc6b9b578b95b213e43786fc023
107a1659879414884064e305372c5631
734df183f70f56af8c738f1f51b2d2b0
3307c3550d086d6f8d06b8a85bc39989
643fb24bd380e2f181c3a958dd465591
5c155bc8acd3d13da786a373040a240e,52e259b808c818e4247af81655f0e195
32f2870925459f5ba1dcf65fee9a08c8
0459580538600b2c4ff56fbc2dda3f8d
78ca76476c7f9ce79c4c0f4d63f80803
faf9d9dd07e9be093311e0eba21182b1
2b5ebea49fd1a7a8a8b94a10d25f0ec5
b896fec03441019f564909b07db0b3d6
f5d256fda01b89f2952ac64ac7cbe846
edaef13be77ad2a413af6bb4498b1ccd
9398961707509100fac0c849a6b3d5d7
96ffa1835f0d6566e86384c96b78b9b1
a4c2d4207408f14b4ffdacae20ca08f7
f84846d7ac6bc61b326ad880cbf28acf
29620dc4b82887160ec1629b3e5c6edc
51d345811357ecfeb79ba814e56d4fc3
d03a1d460db0681e17d2fee4cd66335d
5ec4dc615e90dc940319defc249e5912
20925a2d855e8a15c1e5c48b54337c95
66710a5755b499660b59a3c875cff124
de6707573b047f0d607c2bfac8a8b0fc
1809339e95e54406b183b5c14316b812
20925a2d855e8a15c1e5c48b54337c95
d63fbd5f0d6ac07328e33358cb058a88
507362674ccf915721cfc5d80027956d
b51aec0cfcf0eecbaf583f913cc18f3b
e280f8f908ed6232649d7275c4f3c263
081c152961797040930c8128122e0e00
b5e720842c2c1b3fb3c71309fa4434bc
2e493bb63e94c96bed31ece791476c53
0038f2c6b857ba9e169bc6e31a37e86a
7084eeff99226c4eb5d759ed96990352
faf9d9dd07e9be093311e0eba21182b1
9e392161d38fc307605c2cda6ef2af81
60dec45d8b4bbda8681e85f05e979f95
70160d24b2e92217a49cee2e908fcdf2
ab3d2eb28cbc976e2fafdad1b7ebd482
87ec28e9555f4f5ecbf0a2ac91fa0e75
f7ad1f228ae3049f9d6d2b6d6c53c035
308285789caba675b139eb73d40bab4f
4bfaa99566f1f39a2986e859562f18c1
8f0626f20824a22fb383950427bfdf1d
0509e4793db90b36cec505fb43d428f0
40b0229cbf83c8857e8c9e7d79bec8e9,6f9ef114e4478a961bf3e59d6441f243,4e953a9700fc3a4de58eb3b066eb4c74,6d7e042a000deca140c330ab99896ebd,a0a5dff287d5f43498a81934df34f6e1
5571d29c100d4ecb876ce740ec5a230c
087b12962dc0b886736fbe861fcb7f16
dd746d62539d3641ccee848781413762
d5835f133f559870443026042f3315a2
49c66e069adb221d74fb741237f007f8
bf3bab9f98cf513bd09ffe6e773ab8d8
13087819ac1f0570a175896286155ef6
9d5e7952ff3ecce46cf7a6a76837e51a
8e9d2fe0a1ea2cbff94ceb59acf05afd
7aa3ef507105b4b44498ca9e25dce68e
c3bde1bd54b7318ec7fd8ba0a5ef2799
2a630a08a4f592215e5f0661960aabf5
6767a7ed15098325f2580247363793dc
7084eeff99226c4eb5d759ed96990352
54155858ff0ff417ff7f901493e8d80a
15a89725f831a8cd0e0594c82f2afc91
8e4d39a1e12d173da83ba92224917e76
3c4251078c1b4f76813c5c66da0e66d2
a60305ce45d1bed9759420c05bb74200
9ed539a96c6ffd96f54f63c13fb1e0df
05d4d580b9a9f0692acb5950783e79af
36fac51b1cac71ead04dd03f4f45dcf7
d192e8eca0b215e58fc76ed5e7cdb8d3
93da6de45bac6556d559e27278cb6e54
301ab3d7cd81d361b8bab86f6bf99d95
8a2c67da95795be7b01b0ea588f19c51
4e9a55218ec14c55f9e9acaba510e6fb
df81af52d06780671644c62b3545e350
e78d8dbdbec094b48888c2a9bdf3db31
14850b4cd1651f79eb5235000391da47
bb0692d4a7e038da83171b7279c9cdba
7f9159a0d78aac2a2a88e312e4448a32
92698f95c3f6fad49f138d3a500b24c1
86ed173774a1f3ef085283026d86353d
001b26b67eadea666cc3a9275c676c32
25c2dd2b9807a563dd4b01772a41f685
4d78c3506e84b7ba8a15ef5dd8b1f245
7da26a6a112fc0a4853a40d34e3ddb4d
5571d29c100d4ecb876ce740ec5a230c
cc83b05076086e5e31858b1dfe2860c3
69c03212aced107aa6a570d62cddf377
725be1e44e6b5f9ebf67906a75ec9933
f068075227855de709cd7bea20b94712
0cbd2d21319244a40e32a82d6e227afe
27cf7abf04f836c0fad4b02c2c5eb1cf
8e9d2fe0a1ea2cbff94ceb59acf05afd
577de6021bda1e0ceca478e31f8bfc87
991844d4a0b1784c89f14f0c2c9cd19f
29620dc4b82887160ec1629b3e5c6edc
3442cebc305fbdc04afd63d9e4938a57
3d90ea906736eef7c1c443555b764cbf
3e8502bf992392fb9413a868521f6aaf
ae5c3471f12387be2adebc7922067ff0
4d9ed289a439c416bb1619a3b408930d
45add99671a0f66b8d2b7098f89fc72c
7aa3ef507105b4b44498ca9e25dce68e
3da304722fa16d03f50a47000f7ae920
a1385619e5caccf4b3b83d393c81642d
ee060398a75b39b2a03c9add1f7978e1
dd3d6e9ada3c64b33eb230ecd0c570c4
8f076ef293394c777de8d5c4fc3240ad
97f313290a9dc16097cac7734c1637cc
482e65f984de1d07b79b1ab35f7e7cb4
abd6ebbf2a002a1b194630daecdbd2d4
0da3cbbdbf7158b0981ee29b3d686ca6
b2f82c344a844898d26953f64df2ff83
70140e89c67019a069783f7a71559bc0
faf9d9dd07e9be093311e0eba21182b1
8812b05556753b1ed2a2f439baddfcd1
a7dc01d775e22a34c4caf0cc9bc90273
e049fd711a582a90c5b9e73f4464d4f1
35961793c02f21072b2af72e769af5f1
d3af2d890b6c1331abc0cf1bab1b66e4
58887a74b1a7408d67f6e510b205253a
a74029be428eb715469c37c5c087051d
37b95887f746d30625bd38d8a1589c7e
1e08e6e08db81f79daa1b2c6f3081d75
0c2126a38c0ed90c78862f4d35c122a9
5c90775712b39468a3e22b6deee48708
f20c1b43cb9ce21b83778e28fa70801e
05d4d580b9a9f0692acb5950783e79af
301ab3d7cd81d361b8bab86f6bf99d95
0c2126a38c0ed90c78862f4d35c122a9
b5e720842c2c1b3fb3c71309fa4434bc
b2ef9941ccb75ad33ad5902e97f307bd
e88457aa452f777eef85fbbfd95ec85e
d149059cefe1e067a06889abaf6ae36d
e2026b3693a8d0d1ac381b2541831b9f
299a1aa910c5e3f5853ebc4d95df39c3
dc71ab56ab5e0075a7edf3b6af248022
6c602f815679f5a7ea6eff8574de6c28
3c4251078c1b4f76813c5c66da0e66d2
11a3163af56c93d3f02ccd881a153861
3e8502bf992392fb9413a868521f6aaf
7b4ca419f4a4c4381a36ce3854ddf1da
036972ce68087074133e95ee76713f2a
fbdd29796d1d0fadeb05bd0e264f5df3
45ce9f6602073c6df14af4c53f61b484
559a27d0f30ea0b131cea62ab9546c86
f732cd2547622a112d7cf896c67a9ab2
70160d24b2e92217a49cee2e908fcdf2
48e215170f43f1717d978f0fd56a92fa
a04fc54f775f2776321673d69c80d4ea
637ef19ad1a589d4a570ec593a7a34a5,56b28258fb8ccdbf1f5d4801346a47ca
269735d3c130ac7f21444a8f16977d9b
13bd89481a54c506f4f16cfe1e139d25
087b12962dc0b886736fbe861fcb7f16
18d01ec07210c571629cfe9d55b98026
eb158e420f553716a872ad93cc0ab002
9120cf47d515e5c75609accc846a899e
021c070c1f6250468fa9caf0eae5c2ff
11858f55795ea2ddf27da80247d8793d
b2ef9941ccb75ad33ad5902e97f307bd
261ae85a599bcdbb534339e386445430
a74029be428eb715469c37c5c087051d
d7ddb097e2138e1c72563b6ccb2af019
4f3e930a4c098e0235e7c3beefb4519b
9d5e7952ff3ecce46cf7a6a76837e51a
66ad7e68c5579f0e86e19fb0bcb59c9d
50fd1fbccb1aa184e8cc9353207005c0
9612ba0b6726e0945ffd43aa4c59c8a5
f10a8e559deb772c2b8b8f547e38b21e
dc71ab56ab5e0075a7edf3b6af248022
3fce16d0d5d0004263f8f15e3023b50b
2d71e464e127d071054f66bc966a2aaf
37a51512676179c4e60df9851cfe03d3
9612ba0b6726e0945ffd43aa4c59c8a5
7c960ceb395435846ac66ea3086c970d
6616be150340498249f27ee70f8aa47e
ce692dd8417c8e34746156ce9b799e91
cc634c526fe4da575eac6077a3071644
90d2a26e0963b293fefd214569d17cfb
051c68bc60c123ce99f5008609efbb7d
1486ccdfc852a4c118ab3463b620a466
0c0de09b42bf2d54b04912c9bf635515
0ed3ab81f348ee25c87f92ab4087ec5e
e0ca8ccc957022a3c7ea3ceeb513ca23
e23a131210f3a730d088fe9524ccfba0
b486e4c64373befe35c0dd65be80e1b1
bc85909fa786f72bb236a56a8f17acd6
8b8698cc1746ad3920c7589debfd21de
227d508c1de10b3271147a2a70b0abe2
ebefb82e4d8e381f2cb9a635b45dd9af
4e08f2f6c64e001b5f6095a38982ebc1
35ce84e828c308566b763a7a21450245
2d71e464e127d071054f66bc966a2aaf
5bec040b123435df0d1806ddb50cbe9f
84a89358c67cfbd28163d67eea589c27
53e0a337dab988e3ff85d0fb6f5e8dbd
16f289b12124693df4f5177fb8bcadef
b5f2705bc4649da0b7af267533fe7fdf
38ab3499c5cf480879f7cf34567f24c0
98ac31d4329f872502c152c3cdde4087
72b705952c8dc1538c2e7611b9e731e8
b26b42fa48cc68886ca0018d9893fcb5
571c9d7cb9dc4e76611c09311fc5edc2
eeb94f7eb6bace26301d5aa1ebcab163
a04fc54f775f2776321673d69c80d4ea
07fc67e89397ab658cde9e3dc4c5640e
9e392161d38fc307605c2cda6ef2af81
4e9a55218ec14c55f9e9acaba510e6fb
18d01ec07210c571629cfe9d55b98026
571c9d7cb9dc4e76611c09311fc5edc2
e280f8f908ed6232649d7275c4f3c263
e68f2f8b35cc47352ce750bdc5f40504
1952a815e289a25396905fbe8f29f671
e23a131210f3a730d088fe9524ccfba0
f805d549425c7328c40729b84606ba07
157d68a0e73262e443ad843e7d29195f,4f312b0f37bf9d86333114a4f467ddc3
7a039abc3278bd040255b3b020b8a305
2478beac944acaad42aa81cea341e99c
6a04ee45b8f4727ee9b5bcee145edfa1
a9df6c8208e4ca184b689d42b99ea1cb
6616be150340498249f27ee70f8aa47e
9a7ed6b4667075503f2c3ee97cbf29d1
afe72d2ef971f6330b38c9f1ab219910
f38a2fe99994feb158aa4a165cca1e64
9c4007d4719272d62f8dbe7ee63ff2fc
2478beac944acaad42aa81cea341e99c
503a979ce10f2ec8b7ee25871f90e010
b33ad589799efe4f0ae9a5bb57c2c734
8fa16044e151faa4c7340d13f083c494
5ef139e5e983b02ed0f3fd3d095b1eab
583b77699d72eed9181261b8b8c9aef0
16baf76a47b2c3183210939f73a345ee

 

 

java实现fp-growth算法

标签:eva   +=   提升   lsp   lang   步骤   algorithm   代码   near   

原文地址:https://www.cnblogs.com/xmy20051643/p/11100548.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!