几种常见的字符串匹配算法之PHP代码简释一

写在前面:本文侧重诠释对算法的思考记录过程,忽略其他诸如代码简洁、字符编码等细节问题。

<?php

$str = 'goauabcdislcdnabcdabcdvbuijdks';
$target = 'abcdabcd';
$start = bf_str($str, $target);
$start2 = kmp_str($str, $target);
var_dump($start);
var_dump($start2);

//BF算法:暴力匹配算法或朴素匹配算法,即从被查找的主串的起始位置开始,
//依次向前比对每个位置上的字符,以找出与要查找的目标模式串值和数量都匹配的字符串
//算法复杂度:O(n*m) 注:n为主串的长度,m为模式串长度
function bf_str($str, $target) {
	$n = strlen($str);
	$m = strlen($target);
	$j = 0;
	$i = 0;
	$start = -1;
	for (; $i<$n; $i++) {
		if ($j < $m && $str[$i] != $target[$j]) {
			$j = 0;
			continue;
		} else {
			$j++;
			if ($j >= $m) {
				$start = $i - $m + 1;
				break;
			}
		}
	}
	return $start;
}

//KMP算法:在模式串与主串匹配的过程中,当遇到不可匹配的坏字符的时候,就跳过最长可匹配前缀,
//重新开始匹配,从而避免 BF 算法这种暴力匹配,提高算法性能。
//算法复杂度:O(n+m)
function kmp_str($str, $target) {
	$n = strlen($str);
	$m = strlen($target);
	$next = generate_next($target);
	$j = 0;
	$start = -1;
	for ($i=0; $i<$n; $i++) {
		// $stri = $str[intval($i)];
		// $targetj = $target[intval($j)];
		$stri = substr($str, $i, 1);
		$targetj = substr($target, $j, 1);
		while ($j > 0 && $j < $m && $stri != $targetj) {
			$j = $next[$j-1] + 1;
		}
		if ($stri == $targetj) {
			$j++;
		}
		if ($j == $m) {
			$start = $i - $m + 1;
			break;
		}
	}
	return $start;
}
function generate_next($target) {
	$next = [];//所有好前缀
	$next[0] = -1;
	for ($i=1; $i<strlen($target)-1; $i++) {
		$prefix = substr($target, 0, $i+1);
		$next[$i] = get_repeat_last_num($prefix);
	}	
	return $next;
}

function get_repeat_last_num($str) {
	$middle = floor((strlen($str) - 1) / 2);
	$num = -1;//最长可匹配前缀结尾字符下标
	for ($i=$middle; $i>=0; $i--) {
		$left = substr($str, 0, $i+1);
		$right = substr($str, -$i-1);
		if ($left == $right) {
			$num = $i;
			break;
		}
	}
	return $num;
}

参考来源:https://xueyuanjun.com/books/data-structure-and-algorithms

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值