php- osc,PHP-AC自动机 - osc_eoffv2le的个人空间 - OSCHINA - 中文开源技术交流社区

能高效地匹配字符串,具体原理就不搬了,这边给出PHP的实现代码:

class AcAutomation

{

private $root;

public function __construct($keywords = array())

{

$this->root = $this->createNode();

foreach ($keywords as $keyword) {

$this->addKeyword($keyword);

}

$this->buildFailIndex();

}

/**

* 创建节点

* @param string $value

* @return stdClass

*/

private function createNode($value = "")

{

$node = new stdClass();

$node->value = $value;

$node->next = array();

$node->fail = NULL;

$node->len = 0; // keyword长度,0表示非末尾,非0表示keyword的长度

return $node;

}

/**

* 添加关键词

* @param $keyword

*/

private function addKeyword($keyword)

{

$keyword = trim($keyword);

if (!$keyword) {

return;

}

$cur = $this->root;

$matches = unpack('N*',iconv('UTF-8', 'UCS-4', strtolower($keyword)));

for ($i = 1; isset($matches[$i]); $i++) {

$v = $matches[$i];

if (!isset($cur->next[$v])) {

$node = $this->createNode($v);

$cur->next[$v] = $node;

}

if (!isset($matches[$i+1])) {

$cur->next[$v]->len = $i;

}

$cur = $cur->next[$v];

}

}

/**

* 构造fail指针

*/

private function buildFailIndex()

{

$queue = array();

foreach ($this->root->next as $node) {

$node->fail = $this->root;

$queue[] = $node;

}

while ($queue) {

$node = array_shift($queue);

foreach ($node->next as $child_node) {

$val = $child_node->value;

$p = $node->fail;

while ($p != NULL) {

if (isset($p->next[$val])) {

$child_node->fail = $p->next[$val];

break;

}

$p = $p->fail;

}

if ($p === NULL) {

$child_node->fail = $this->root;

}

$queue[] = $child_node;

}

}

}

/**

* 搜索

* @param $content

* @return array

*/

public function search($content)

{

$pos_list = array();

$p = $this->root;

$matches = unpack('N*',iconv('UTF-8', 'UCS-4', strtolower($content)));

for ($i = 1; isset($matches[$i]); $i++) {

$val = $matches[$i];

while (!isset($p->next[$val]) && $p != $this->root) {

$p = $p->fail;

}

$p = isset($p->next[$val]) ? $p->next[$val] : $this->root;

$temp = $p;

while ($temp != $this->root) {

if ($temp->len) {

$pos_list[] = array($i - $temp->len, $i);

}

$temp = $temp->fail;

}

}

return $pos_list;

}

}

Example:

$content = file_get_contents(dirname(__FILE__).'/content.txt');

$keywords = array('复杂度','个数','返回','代表','性能','数据','GET','安全性','耗时','优化','文档','并发','类型');

$ac = new AcAutomation($keywords);

$res = $ac->search($content);

foreach ($res as $pos) {

echo mb_substr($content,$pos[0],$pos[1] - $pos[0],'UTF-8'),PHP_EOL;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值