php 实现串查找Horspool

来源:互联网 发布:傲剑坐骑升级数据大全 编辑:程序博客网 时间:2024/05/17 06:20
<?php//Horspool 算法//从右边开始扫面pattern(长度为m)//假设串与pattern最后一个字符是c,当c在不同的情况下移动距离如下//1.在模式中不存在c,直接向右移动m//2.在模式中存在c,但是不是最后一个字符,那么把模式最右边的c和当前串中的c对齐//3.如果模式最后一个字符恰好和当前字符c相同,但是模式前m-1个字符不存在c了,那么好使直接移动m长度(类似于1)//4.如果模式最后一个字符恰好和当前字符c相同,但是模式前m-1个字符存在c,那么把模式最右边的c和当前串中的c对齐(类似于2)//例如://串:s0         D    sn//p:    E A B C R //这里pattern中不存在D了,直接右移5个单位//p:    E D D C R //这里pattern中有D ,那么把pattern最右边的D移动来和当前串中D对齐,即移动2个单位//p:    A B C E D //这里m-1 以前都没有D 了 直接移动 5个单位、//p:    A D D E D //吧下一个D(最右边)移动来和当前串中D对齐,2个单位//时间复杂度为O(n),最差为(O(m*n))//实现$str     = 'dfhdiidahjghjddnfioandlsfhoihadlfsheihsfnnsoifdsfadflrfhjoendlknflaerju';$pattern = 'sheihsfn';//预处理pattern生成移动表function shiftTable($p){$m = strlen($p);$table = array();//这里指处理pattern前m-1字符for($i=0;$i<$m-1;$i++){$table[$p{$i}] = $m-1-$i;}return $table;}$count = 0;//count用于标记移动了多少次function HorsPool($str,$p,&$count){$m = strlen($p);$j=$m-1;$table = shiftTable($p);while($j<=strlen($str)-1){$i = 0;while($i<$m&&$p{$m-1-$i}==$str{$j-$i}){$i++;}if($i==$m){//匹配成功return $j-$m+1;}else{//向右移动串$count++;$j+= isset($table[$str{$j}])?$table[$str{$j}]:$m;}}//匹配不成功return -1;}$pos = HorsPool($str, $pattern, $count);echo $pos,'--',$count,'<br/>';///对应的kmp算法function getNext($p){$i = 0;$k = -1;$next = array(-1);while($i<strlen($p)){if($k==-1||$p{$i}==$p{$k}){$i++;$k++;$next[$i] = $k;}else {$k = $next[$k];}}return $next;}$count = 0;function KMP($str,$pattern,&$count){$i=$j=0;$next = getNext($pattern);while($i<strlen($str)&&$j<strlen($pattern)){if($j==-1||$str{$i}==$pattern{$j}){$i++;$j++;}else{$count++;$j= $next[$j];}}if($j>=strlen($pattern)){return $i-strlen($pattern);}return -1;}$pos = KMP($str, $pattern, $count);echo $pos,'--',$count;?>

0 0
原创粉丝点击