接着上文【基于统计的无词典的高频词抽取(一)——后缀数组字典序排序】,本文主要讲解高频子串抽取部分。

如果看过上一篇文章的朋友都知道,我们通过 快排 或 基数排序算出了存储后缀数组字典序的PAT数组,以及PAT数组内,每每两个子串的最大公共前缀数组LCP。

我们可以通过LCP来计算出一个字符串在语料库中出现的次数。那怎么计算呢?我们先看看下面一个简单的例子:

【例】我们还是以上一篇文章中的字符串“abcba”为例,经过对后缀数组字典序排序(过程参照前一篇),可以得到以下的结果:

由上图中的PAT和LCP两个数组我们可以知道:“a”的频率为2,“b”的频率为2。

计算方式其实很简单,从左扫描LCP数组,如果LCP[i]>=n(n为自定义的两个字符串公共子串的长度的最小长度,上面例子中设置为1),LCP[0]=1符合候选规则,则看PAT[0]=4,意思是说“abcba”这个字符串中的第PAT[i]+1=5个后缀子串,也就是“a”,我们知道,LCP表示的是相邻的两个PAT间的最长公共前缀,故“a”的频率=LCP[0]+1=2次。同理,可以知道“b”出现两次(S[PAT[3]]=b,LCP[2]=1,所以b出现的次数为1+1=2,刚开始有点难理解,但其实很好理解的)

分析完上面的例子,我们应该更加清楚的了解了LCP的作用,就是计算一个字符串在一个语料库中出现的次数,现在我们就用伪代码(文字)一步一步分析这个过程:

①  设定c 的初值为0;

②  从LCP位置c开始扫描直至索引i,有LCP[i]≥n;

③  记录LCP[i]的值,继续向前扫描,直至位置j,有LCP[j]<LCP[i]。如果存在位置x(i<x≤j),有LCP[x]>LCP[i],则令c=x,否则c=j;

④  提取字符串S,其在T中的开始位置为PAT[i],长度为LCP[i],S出现的次数为j-k,记录串S出现的次数j-k;

⑤  返回步骤②,提取下一个字符串,直至扫描完LCP数组;

⑥  对所记录的所有字符串,按照出现次数进行排列,输出所有出现次数≥n的字符串序列;

这个过程中要注意存在这样这样的一种情况:假设LCP为:1,1,3,2,1,0,0,2,...,那么1,1,3,2,1 我们知道,第一个字符出现了6次,而中间的3那个串出现了2次,但是计算2那个串的时候,因为前面的3>2,所以我们必须往前回溯,也就是说这里2那个串出现的次数是2+1=3次;

代码实现过程如下(经测试,对30万的数组查找耗时12s左右,没做过多优化,大家可以根据此思路来做优化):

 public static void ScanLCP(List < StringFrequency > stringFrequncy, int[] LCP, int count, int start, int minLen, int maxLen)
{
var _START = start;
while (_START <= count - )
{
var _LCP = _START;
var isFirst = true;
var isLarge = true;
var isContinue = true;
int j = ;
int i = _START;
for (; i < count; i++)
{
if (LCP[_START] > maxLen)
{
_START += ;
break;
}
if (isFirst)
{
if (i - >= )
{
if (LCP[i - ] >= LCP[i])
{
for (var k = i - ; k >= ; k--)
{
if (LCP[k] >= minLen && LCP[k] != LCP[i])
j += ;
else
{
if (LCP[k] == LCP[i])
{
isContinue = false;
j = ;
}
break;
}
}
}
}
}
if (LCP[i] >= minLen && LCP[i] >= LCP[_LCP] && isContinue)
{
if (isFirst)
{
_LCP = i;
isFirst = false;
}
if (isLarge && LCP[i] > LCP[_LCP])
{
_START = i;
isLarge = false;
}
}
else
{
if ((isFirst && LCP[i] < minLen) || !isContinue)
_START = i + ;
else
{
if (isLarge && LCP[i] < LCP[_LCP])
_START = i;
if (LCP[_LCP] <= maxLen)
{
var sf = new StringFrequency();
sf.Position = _LCP;
sf.Times = (i - _LCP) + + j;
stringFrequncy.Add(sf);
}
}
break;
}
}
}
}

看起来好像挺玄乎,其实,到这一步的时候,对语料库的分析抽词已经初见成效了,下图,是我对《人民日报》2012年8月份到11月份的报纸的分析抽取,进行了后缀数组排序,LCP计算后的结果:

现在的结果还不够精确,等做完子串归并,最大熵模型后,可以获得更精准的结果(Ps:人民日报涉及的内容太片面,实际情况下,要采集涉及面广的语料库)

好了,第二部分就先讲到这里,如果觉得文章对您有用或者对其他人有帮助,请帮忙点文章下面的“推荐”;如果文章有任何纰漏,欢迎指正,谢谢!

基于统计的无词典的高频词抽取(二)——根据LCP数组计算词频的更多相关文章

  1. 词频分析 评论标签 nltp APP-分析买家评论的评分-高频词:二维关系

    0-定评论结果:好评.差评,1星.4星,二元化为“积极.消极”,取一元的数据为样本 1-得到词频结果:如手机类的“积极样本”得到前10的高频词:运行(run running ran).内存(memor ...

  2. 【爬虫+情感判定+Top10高频词+词云图】“谷爱凌”热门弹幕python舆情分析

    一.背景介绍 最近几天,谷爱凌在冬奥会赛场上夺得一枚宝贵的金牌,为中国队贡献了自己的荣誉! 针对此热门事件,我用Python的爬虫和情感分析技术,针对小破站的弹幕数据,分析了众网友弹幕的舆论导向,下面 ...

  3. 【爬虫+情感判定+Top10高频词+词云图】“刘畊宏“热门弹幕python舆情分析

    一.背景介绍 最近一段时间,刘畊宏真是火出了天际,引起一股全民健身的热潮,毕竟锻炼身体,是个好事! 针对此热门事件,我用Python的爬虫和情感分析技术,针对小破站的弹幕数据,分析了众多网友弹幕的舆论 ...

  4. 【爬虫+情感判定+Top10高频词+词云图】"王心凌"热门弹幕python舆情分析

    目录 一.背景介绍 二.代码讲解-爬虫部分 2.1 分析弹幕接口 2.2 讲解爬虫代码 三.代码讲解-情感分析部分 3.1 整体思路 3.2 情感分析打标 3.3 统计top10高频词 3.4 绘制词 ...

  5. kaggle信用卡欺诈看异常检测算法——无监督的方法包括: 基于统计的技术,如BACON *离群检测 多变量异常值检测 基于聚类的技术;监督方法: 神经网络 SVM 逻辑回归

    使用google翻译自:https://software.seek.intel.com/dealing-with-outliers 数据分析中的一项具有挑战性但非常重要的任务是处理异常值.我们通常将异 ...

  6. NLP系列-中文分词(基于统计)

    上文已经介绍了基于词典的中文分词,现在让我们来看一下基于统计的中文分词. 统计分词: 统计分词的主要思想是把每个词看做是由字组成的,如果相连的字在不同文本中出现的次数越多,就证明这段相连的字很有可能就 ...

  7. [LeetCode] Top K Frequent Words 前K个高频词

    Given a non-empty list of words, return the k most frequent elements. Your answer should be sorted b ...

  8. 5分钟Serverless实践 | 构建无服务器的敏感词过滤后端系统

    前言 在上一篇“5分钟Serverless实践”系列文章中,我们介绍了什么是Serverless,以及如何构建一个无服务器的图片鉴黄Web应用,本文将延续这个话题,以敏感词过滤为例,介绍如何构建一个无 ...

  9. 图解kubernetes scheduler基于map/reduce无锁设计的优选计算

    优选阶段通过分离计算对象来实现多个node和多种算法的并行计算,并且通过基于二级索引来设计最终的存储结果,从而达到整个计算过程中的无锁设计,同时为了保证分配的随机性,针对同等优先级的采用了随机的方式来 ...

随机推荐

  1. 自定义事件 js

    // 原理如下// 创建 类型为HTMLEvents的事件 var evt = document.createEvent("HTMLEvents"); // 初始化 自定义eee ...

  2. IIS7web服务器调试ASP.net程序遇到的一些故障的解决办法

    1. [由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面] 故障描述:[由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面] ...

  3. 关于mybatis缓存配置详解

    一级缓存: 一级缓存是默认的. 测试:在WEB页面同一个查询执行两次从日志里面看同样的sql查询执行两次. 2次sql查询,看似我们使用了同一个sqlSession,但是实际上因为我们的dao继承了S ...

  4. [leetcode]426. Convert Binary Search Tree to Sorted Doubly Linked List二叉搜索树转有序双向链表

    Convert a BST to a sorted circular doubly-linked list in-place. Think of the left and right pointers ...

  5. 文件Move操作

    #coding=utf-8 import os import shutil stra = "G:/should/v3/a" strb = "G:/should/v3/b& ...

  6. ef linq 访问视图返回结果重复

    根据检测到的语句查询和linq查询出来的结果不一致,linq查询出重复的数据,原因不明,已改用ef直接查询视图,也许以后某一天突然就解决了,先mark下.

  7. 【转】MEF程序设计指南二:Silverlight中使用CompositionInitializer宿主MEF

    MEF可以在传统应用程序中使用(包括桌面的Winform.控制台程序和Web的ASP.NET),也可以在RIA的Silverlight中使用.在Silverlight中只是宿主的方式有所不同,实际上在 ...

  8. 使用JMX监控Storm的nimbus、supervisor、woker

    可以通过在storm.yaml中增加如下样例的配置, 启动JMX来监控storm的各个角色. 其中对于Worker的监控,因为一个节点上可以有多个work,为了防止端口号重复导致启动失败,所以用动态代 ...

  9. 常用C字符串函数

    static void str_repalce(char *src,char *from,char *to) {     char *p,*q;     int lenFrom;     int le ...

  10. ubuntu16下Elasticsearch5.1.1安装部署

    本人在安装es5.1.1版本时候整理的一些过程,参照了网上部分过程:其中过程中也出现一些其它问题,出现的问题和解决方案都整理在此文中. 1Elasticsearch5.1.1安装 到ES官网https ...