java实现fp-growth算法
最近公司项目上用到频繁项发现算法,于是就用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;}@Overridepublic 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>() {@Overridepublic 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   LIST</br>* T0   1,2,3,4</br>* T1   1</br>* T2   3,4</br>* T3   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);elsemergeSort(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 arraysif (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 srcint 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 destfor (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++];elsedest[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 arraysif (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 srcint 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 destfor (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++];elsedest[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;@Overridepublic boolean nodeCompare(String target, String source) {return StringUtils.equals(target, source);}/*** 节点内容需要按项头表统计数量逆序排序*/@Overridepublic Comparator<String> nodeEleCompare(FpTreeHeader<String, Integer> header) {if (comparetor == null) {comparetor = new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {int i = header.get(o2) - header.get(o1);return i;} };}return comparetor;}@Overridepublic 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]
注意的问题:
- jdk7以上在做排序时候不要用Collection工具自带的排序,有坑滴;
- 关于fptree树,节点顺序并不会影响结果;
- 关于频繁项挖掘过程中,可能会出现很多频繁项集,所以在计算过程中注意内存问题,当然,解决办法就是在resultHandler方法中进行频繁项集的结果合并,参数将会传入频繁度,所以result中的数据可以和已有结果进行比较,如果result+频繁度已经在resultList中存在,则不处理此结果,如果resultList中的结果被包含与result中,更新resultList对应项,这样只保持最大结果集,舍弃中间结果来节省内存,同时对result应该做deepCopy,不然GC时释放不掉引用,内存会溢出;
- 《机器学习实战》中的代码有错,下面的是修改过的;
- 对于上亿上十亿的输入数据,速度提升办法是把数据切成几个片,每个片都跑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 = nameValueself.count = numOccurself.nodeLink = Noneself.parent = parentNode #needs to be updatedself.children = {} def inc(self, numOccur):self.count += numOccurdef disp(self, ind=1):print ' '*ind, self.name, ' ', self.countfor child in self.children.values():child.disp(ind+1)def createTree(dataSet, minSup=1): #create FP-tree from dataset but don't mineheaderTable = {}#go over dataSet twicefor trans in dataSet:#first pass counts frequency of occurancefor item in trans:headerTable[item] = headerTable.get(item, 0) + dataSet[trans]for k in headerTable.keys(): #remove items not meeting minSupif headerTable[k] < minSup: del(headerTable[k])freqItemSet = set(headerTable.keys())#print 'freqItemSet: ',freqItemSetif len(freqItemSet) == 0: return None, None #if no items meet min support -->get outfor k in headerTable:headerTable[k] = [headerTable[k], None] #reformat headerTable to use Node link #print 'headerTable: ',headerTableretTree = treeNode('Null Set', 1, None) #create treefor tranSet, count in dataSet.items(): #go through dataset 2nd timelocalD = {}for item in tranSet: #put transaction items in orderif 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 itemsetreturn retTree, headerTable #return tree and header tabledef updateTree(items, inTree, headerTable, count):if items[0] in inTree.children:#check if orderedItems[0] in retTree.childreninTree.children[items[0]].inc(count) #incrament countelse: #add items[0] to inTree.childreninTree.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 itemsupdateTree(items[1::], inTree.children[items[0]], headerTable, count)def updateHeader(nodeToTest, targetNode): #this version does not use recursionwhile (nodeToTest.nodeLink != None): #Do not use recursion to traverse a linked list!nodeToTest = nodeToTest.nodeLinknodeToTest.nodeLink = targetNodedef ascendTree(leafNode, prefixPath): #ascends from leaf node to rootif leafNode.parent != None:prefixPath.append(leafNode.name)ascendTree(leafNode.parent, prefixPath)def findPrefixPath(basePat, treeNode): #treeNode comes from header tablecondPats = {}while treeNode != None:prefixPath = []ascendTree(treeNode, prefixPath)if len(prefixPath) > 1: condPats[frozenset(prefixPath[1:])] = treeNode.counttreeNode = treeNode.nodeLinkreturn condPatsdef 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 tablenewFreqSet = 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 basemyCondTree, myHead = createTree(condPattBases, minSup)#print 'head from conditional tree: ', myHeadif 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 simpDatdef createInitSet(dataSet):retDict = {}for trans in dataSet:# retDict[frozenset(trans)] = 1retDict[frozenset(trans)] = retDict.get(frozenset(trans), 0) + 1return retDictimport twitter from time import sleep import redef 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 pageresultsPages = []for i in range(1,15):print "fetching page %d" % isearchResults = api.GetSearch(searchStr, per_page=100, page=i)resultsPages.append(searchResults)sleep(6)return resultsPagesdef 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 myFreqListsimpDat = [] 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:continueprint iprint '============================' 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
转载于:https://www.cnblogs.com/xmy20051643/p/11100548.html
java实现fp-growth算法相关推荐
- Frequent Pattern 挖掘之二(FP Growth算法)(转)
FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对.为了达到这样的效果,它采用了一种简洁的数据结 ...
- MapReduce框架下的FP Growth算法概述
转载自:http://blog.sina.com.cn/s/blog_68ffc7a40100uebi.html 前面的博客分析了关联分析中非常重要的一个算法-FP Growth.该算法根据数据库在内 ...
- FP Growth算法
转载自:http://blog.sina.com.cn/s/blog_68ffc7a40100uebg.html FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法 ...
- MapReduce框架下的FP Growth算法详解
转载自:http://blog.sina.com.cn/s/blog_68ffc7a40100uebk.html Sharding 这一步没什么好讲的,将数据库分成连续的大小相等的几个块,放置在不同的 ...
- FP Growth算法详解
看了n多资料,就这篇说的比较详细,适合初学者 FP树构造 FP Growth算法利用了巧妙的数据结构,大大降低了Aproir挖掘算法的代价,他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对 ...
- FP Tree算法原理总结(转)
FP Tree算法原理总结 转自: https://www.cnblogs.com/zhengxingpeng/p/6679280.html 总结得太好了. FP Tree算法原理总结 在Aprior ...
- FP Tree算法原理
作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈.为了解决这个问题,FP Tree算法(也称FP Growth算法)采用了一些技巧,无论多少数据,只需要扫描两次数据集 ...
- 基于R的FP树fp growth 关联数据挖掘技术在煤矿隐患管理
研究煤矿隐患数据的挖掘以实现海量隐患数据的有效利用,在分析矿山数据挖掘枝术和煤矿隐患数据特点的基础上,提出煤矿隐患数据挖掘是矿山数字化的重要组成部分,给出煤矿隐患数据挖掘的概念,设计了煤矿隐患数据挖掘 ...
- java实现国密算法
java实现国密算法 一.国秘算法SM4 1.1 引入依赖 1.2 使用对称密码算法SM4加解密 二.SM3是哈希算法 2.1 案例 三.SM2算法(公钥私钥是字节类型) 3.1 SM2签名和验签 3 ...
- java培训:Java的十大算法
想要学好java语言,就要打好基础,java要学习的东西有很多,今天小编就来和大家说下java的十大算法. 算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个 ...
最新文章
- @Autowired所有的东西!
- LeetCode 1506. Find Root of N-Ary Tree(异或)
- python3安装pymysql_python安装PyMySQL
- Android--百度地图之基础地图(三)
- 【STM32】高级定时器、通用定时器和基本定时器---配置寄存器产生PWM
- Linux Shell编程三
- allure 测试报告本地打开_Allure自动化测试报告我是这样用的
- Python爬虫实践(二) -- 爬虫进阶:爬取数据处理、数据库存储
- c++字符串逆序输出
- 小学计算机专业说课稿模板,小学信息技术计算机的小管家说课稿
- 北京邮电大学计算机网络教材,北京邮电大学《计算机网络》4.pdf
- Windows下的YouTube-dl与FFmpeg下载安装配置
- opencv抠出圆形区域_用OpenCV检测圆形区域(包含大量小对象)
- Python 批处理文件(全)
- 数据库应用系统的四个层次划分
- 鼠标精灵对码软件_暗影精灵6游戏主机评测
- 力扣每日一题第495题提莫攻击
- TensorFlow 2.X获取Flops和参数量(parameters)的方法(2022年)
- 酷派手机COOLPAD5380CA动态权限允许无法点击
- 重装Win10系统之U盘启动盘的制作(详细教程)
热门文章
- Stata数据处理:物价指数-(CPI)-的导入和转换
- IOTSWC欧洲工业物联网解决方案大会-2019
- file open error: [Errno 2] No such file or directory: '\xe6\xb5\x8b\xe8\xaf\x95.txt'
- 阿里云服务器租用价格表,阿里云服务器优惠
- 群晖套件 Transmission 汉化
- iOS12适配适配iPhone XR/iPhone XS Max
- 微信小程序开发出现Page “pages/detail/detail” has not been registered yet.
- Windows禁止某个软件联网保姆级教程
- Win10系统怎样让打开图片方式为照片查看器
- 接口测试之postman