<?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;
?>
php 实现串查找Horspool
最新推荐文章于 2025-08-03 03:00:00 发布