aho-corasick php,更快的Aho-Corasick PHP实现
在
PHP中是否有一个
Aho–Corasick的工作实现?维基百科文章中提到了一个
Aho-Corasick string matching in PHP:
/*
This class performs a multiple pattern matching by using the Aho-Corasick algorythm, which scans text and matches all patterns "at once".
This class can:
- find if any of the patterns occours inside the text
- find all occourrences of the patterns inside the text
- substitute all occourrences of the patterns with a specified string (empty as well)
Example of usage:
$words = array{ "ananas", "antani", "assassin" };
$pm = new PatternsMatcher();
$pm->patterns_array = $words;
if ( $pm->multipattern_match( "banananassata" ) ) {
echo "pattern found!!";
}
This class is definitively open-source under no particular license.
If you use it, let me know what you think about it and how to improve it:
Marco Nobile (Università degli studi di Milano-Bicocca) - marco.nobile@unimib.it
The code wasn't deeply tested, use as your own risk.
P.S.: in order to use it as a bad words black-lister, I suggest you to wrap the words with two empty spaces (eg.: "ananas"-->" ananas ")
in order to avoid sub-patterns detection. Moreover, better delete the word by substituting it with an empty space instead of the empty string.
*/
class PatternsMatcher {
var $patterns_array;
var $text;
var $finals;
var $delta;
var $phi;
var $container;
var $M;
var $ready;
/* costruttore */
function PatternsMatcher() {
$this->finals = array();
$this->phi = array();
$this->container = array();
$this->delta = array();
$this->patterns_array = array();
$this->ready = false;
}
/* import new pattern */
function import_pattern( $p ) {
$this->patterns_array[]=$p;
}
/* shortcuts */
function deltafun( $indice, $carattere ) {
return $this->delta[$indice][$carattere];
}
function phifun( $indice ) {
return $this->phi[$indice+1];
}
/* chiamata (ricorsiva) che controlla l'esistenza di prefissi uguali a questa stringa.
il parametro limita il numero di stati oltre il quale non verificare */
function check_border( $string , $state ) {
/* se la stringa è lunga 0 non ho trovato prefissi buoni */
if ( strlen($string)==0 )
return 0;
/* se la stringa è più lunga, controlliamo non sia contenuta in un prefisso
ovvero in una delle stringhe identificate dagli stati precedenti (
for ($j=0; $j
/* se questo suffisso è uguale ad un pattern, ritorna lo stato corrispondente */
if ( $string == $this->container[ $j ] )
return $j+1;
}
// trovato nulla, riprovo con la sottostringa
return $this->check_border( substr( $string, 1 ) , $state );
}
/* costruisce la tabella phi (failure) */
function build_phi( ) {
/* valore di partenza */
$this->phi[0]=0;
/* foreach stato */
foreach ( $this->container as $index => $string ) {
/* controlla se il prefisso di questo pattern ha un suffisso che è...
prefisso di un pattern tra quelli identificati dagli stati 0..index */
$this->phi[ $index ] = $this->check_border( $string , $index );
}
return $this->phi;
}
/* costruisce la tabella delta (next) */
function build_delta( ) {
/* somma delle lunghezze dei patterns */
$this->M = 0;
/* ultimo stato */
$last_state = 0;
/* contiamo i caratteri dei patterns */
foreach( $this->patterns_array as $pattern ) {
$lunghezza = strlen( $pattern );
$this->M += $lunghezza;
}
/* for each pattern... */
foreach( $this->patterns_array as $key => $pattern ) {
/* convertiamo le stringhe in array di caratteri */
$string = $pattern;
$lun = strlen($pattern);
/* stati iniziali */
$asf_state = 0;
$in_pattern_index = 0;
/* tengo traccia dei prefissi, mi rende la vita più semplice dopo */
$temp = "";
/* finché il pattern non è esaurito e la delta è diversa da NIL... */
while( ($in_pattern_index < $lun) & ( !is_null( $this->deltafun( $asf_state , $string[$in_pattern_index] ) ) ) ) {
// segui un percorso pre-esistente
$asf_state = $this->deltafun( $asf_state , $string[ $in_pattern_index ] );
// aggiorna il prefisso fin quì
$temp.=$string[ $in_pattern_index ];
// cambia carattere del pattern
$in_pattern_index++;
}
/* crea gli eventuali nuovi stati */
while( $in_pattern_index
// salva i prefissi aggiuntivi
$temp.=$string[ $in_pattern_index ];
$this->container[] = $temp;
// nuovo stato
$last_state++;
// salva in delta
$this->delta[ $asf_state ][ $string[ $in_pattern_index ] ] = $last_state;
// prossimo carattere (se c'è)
$in_pattern_index++;
$asf_state = $last_state;
}
/* è uno stato finale! */
$this->finals[ $asf_state ] = true;
}
return $this->delta;
}
/* precalcola le tabelle phi e delta; se già calcolate, le ritorna direttamente */
function generate() {
/* cache: se abbiamo già precalcolato le tabelle, ritornale direttamente */
if ($this->ready) return;
/* ordina lessicograficamente */
sort( $this->patterns_array, SORT_STRING );
/* precalcula le tabelle */
$this->build_delta( );
$this->build_phi( );
/* abbiamo precalcolato */
$this->ready = true;
}
/* Aho-Corasick standard */
function multipattern_match( $text ) {
// generate tables
$this->generate();
// necessario per prendere anche le prime occorrenze della frase (es.: pattern = " ab " in "ab ac ").
$text = " ".$text;
$i=0;
$stato=0;
while ( $i
$n = $this->delta[ $stato ][ $text[$i] ];
$stato =
is_null($n)? $this->phi[ $stato ] : $n;
if ( $this->finals[ $stato] ) {
return $i;
}
$i++;
}
return -1;
}
/* Aho-Corasick che trova tutte le occorrenze (ritorna un array di tuple {posizione,stringa} ) */
function multipattern_match_array( $text ) {
// generate tables
$this->generate();
// necessario per prendere anche le prime occorrenze della frase (es.: pattern = " ab " in "ab ac ").
$text = " ".$text;
$i=0;
$stato=0;
$result = array();
$temp = "";
while ( $i
$n = $this->deltafun( $stato , $text[$i] );
$stato =
is_null($n)? $this->phi[ $stato ] : $n;
$temp =
$stato == 0?
"" : $temp.$text[$i];
if ( $this->finals[ $stato] ) {
$result[] = array($temp,$i);
// echo $temp;
}
$i++;
}
return $result;
}
/* Aho-Corasick modificato per la cancellazione di pattern (blacklist).
Il parametro specifica con quale sequenza sostituire lo spazio vuoto */
function remove_substrings( $text , $with = "" ) {
// genera le tabelle
$this->generate();
// necessario per prendere anche le prime occorrenze della frase (es.: pattern = " ab " in "ab ac ").
$text = " ".$text;
// contatore sul T
$i=0;
// contatore sul T' (output)
$j=0;
// contatore su P
$k=0;
// stato sull'ASF
$stato=0;
// non ricalcolare la dimensione del testo tutte le volte!
$luntext = strlen($text);
// preallochiamo il testo in uscita T' (necessario per le idiosincrasie di PHP)
$nuovo = str_repeat( " ", $luntext ) ;
/* finché ci sono caratteri nel testo... */
while ( $i
// prox stato su ASF
$n = $this->deltafun( $stato , $text[$i] );
// è null? usiamo phi
$stato =
is_null($n)? $this->phifun( $stato ) : $n;
// aggiorniamo la posizione nella sottostringa (utile per fare backtrack dopo la sostituzione)
$k =
$stato == 0?
0 : $k+1;
// piazza il nuovo carattere
$nuovo[$j] = $text[$i];
/* stato di accettazione! cancella all'indietro e riparti */
if ( $this->finals[ $stato] ) {
// backtracking (equivale a cancellare i caratteri)
$j -= $k;
$k=0;
// abbiamo cancellato della roba. dobbiamo riposizionarci sull'ASF!
$n = $this->deltafun( $stato , substr($with,-1) );
$stato =
is_null($n)? $this->phifun( $stato ) : $n;
// ci posizioniamo sull'ultimo carattere della stringa con cui abbiamo sostituito il pattern
$i--;
}
// muoviamo i puntatori
$j++; $i++;
}
// non ritorniamo l'intera stringa ma solo quella lunga quanto il risultato
return substr( $nuovo , 0, $j );
}
}
但是我很难用它.它适用于婴儿示例,但如果我尝试加载数千个关键字,则脚本超过30秒加载限制.
aho-corasick php,更快的Aho-Corasick PHP实现相关推荐
- 正则表达式匹配可以更快更简单 (but is slow in Java, Perl, PHP, Python, Ruby, ...)
source: https://swtch.com/~rsc/regexp/regexp1.html translated by trav, travmymail@gmail.com 引言 下图是两种 ...
- 比Momentum更快:揭开Nesterov Accelerated Gradient的真面目NAG 梯度下降
d为累计梯度 作为一个调参狗,每天用着深度学习框架提供的各种优化算法如Momentum.AdaDelta.Adam等,却对其中的原理不甚清楚,这样和一条咸鱼有什么分别!(误)但是我又懒得花太多时间去看 ...
- 使用现场总线更快更远
使用现场总线更快更远 Going faster and further with Fieldbus PROCENTEC等行业专家表示,基于RS-485的现场总线技术(PROFIBUS®)和工业以太网( ...
- TensorRT 3:更快的TensorFlow推理和Volta支持
TensorRT 3:更快的TensorFlow推理和Volta支持 TensorRT 3: Faster TensorFlow Inference and Volta Support 英伟达Tens ...
- SOLOv 2:实例分割(动态、更快、更强)
SOLOv 2:实例分割(动态.更快.更强) SOLOv2: Dynamic, Faster and Stronger 论文链接: https://arxiv.org/pdf/2003.10152.p ...
- qt 显示加速_新能源 | 吉利星越ePro上市 补贴后17.58万起售 加速更快油耗更低
点击上方"蓝字"关注我们 新车速递 | 车市速报 吉利星越ePro上市 补贴后17.58万起 加速更快油耗更低 编辑 | 马 妍 排版 | 马 妍 「本文阅读时长约为3分钟 ...
- 使用Python,dlib中新型、更快、更小的5点面部标志检测器检测人脸、眼睛、鼻子
这篇博客将介绍一个新的dlib面部标志检测器--5点人脸标志模型,它比原始版本更快(提高了8-10%),效率更高,模型更小(降低了10倍). 该5点面部标志检测器被认为是最初随dlib库一起分发的68 ...
- 更好的Java虚拟机Zing: 更好的性能,无停顿,更快的启动
Zing虚拟机文档Understanding Java Garbage Collection(了解Java垃圾收集) 首先说明这个Zing是收费的,但是他也是优秀的,我觉得我们可以研究下他的一些思想对 ...
- CSS vs. JS Animation: 哪个更快
CSS vs. JS Animation: 哪个更快? CSS vs. JS Animation: 哪个更快? 基于JavaScript的动画竟然已经默默地比CSS的transition动画快了?而且 ...
- CSS 和 JS 动画哪个更快
基于Javascript的动画暗中同CSS过渡效果一样,甚至更加快,这怎么可能呢?而Adobe和Google持续发布的富媒体移动网站的性能可媲美本地应用,这又怎么可能呢? 本文逐一遍览了基于Javas ...
最新文章
- 给热爱学习的同学们推荐一些顶级的c# Blogs链接
- PIE SDK点元素的绘制
- 了解Django之前
- Linux下搭建jenkins+svn+http+maven自动化部署
- android10位置信息,Android 11 中的位置信息更新
- Linux Kernel 4.20 生命周期已结束,建议迁移 5.0
- SAP Spartacus Loader Meta Reducer学习笔记 - loaderReducer
- IA-32系统编程指南 - 第三章 保护模式的内存管理【2】
- Hbase二级索引+CDH+Lily
- Android 编码规范:(七)避免使用终结方法
- 小米10T系列新机曝光:后置64MP三摄 辨识度超高
- 老哥,帮我看下这个 0day exploit:安全研究员遭疑似国家黑客社工,有人不幸中招...
- 手机中必备的黑科技App,个个好用至极,现在的你一定需要
- 纷杂的Spring-boot-starter: 1 应用 日志 和 spring- boot- starter- logging
- 关于visual studio 2005的中文版下载(最新详细下载点)
- Win11中文包下载失败?Win11无法安装中文包语言包解决方法
- Ubuntu8.04上用飞信 libfetion
- Vue路由的页面跳转打开新页面
- VMware虚拟机安装黑苹果
- 移动端web及app设计尺寸