php字符串匹配算法,字符串查找算法及原理

面试题: 判断字符串是否在另一个字符串中存在?

面试时发现好多人回答不好, 所以就梳理了一下已知的方法, 此文较长, 需要耐心的看下去。从实现和算法原理两方面解此问题, 其中有用PHP原生方法实现也有一些业界大牛创造的算法。

实现

方法一: 语言特性-内置函数

/* strpos示例 */

// test

echo 'match:', strpos('xasfsdfbk', 'xasfsdfbk') !== false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', strpos('xasfsdfbk', 'fbk') !== false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', strpos('xasfsdfbk', 'xs') != false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', strpos('xasfsdfbk', 'sfs') !== false ? 'true' : 'false', ';', PHP_EOL;

// code

strpos('xasfsdfbk', 'sfs');

// mb* 相关的函数也可, 比如说mb_strpos是基于字符数执行一个多字节安全的 strpos() 操作。

函数

描述

版本

查找字符串首次出现的位置

PHP 4, PHP 5, PHP 7

查找字符串首次出现的位置(不区分大小写)

PHP 5, PHP 7

计算指定字符串在目标字符串中最后一次出现的位置

PHP 4, PHP 5, PHP 7

计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写)

PHP 5, PHP 7

查找字符串在另一个字符串中首次出现的位置

PHP 4 >= 4.0.6, PHP 5, PHP 7

查找字符串的首次出现

PHP 4, PHP 5, PHP 7

strstr() 函数的忽略大小写版本

PHP 4, PHP 5, PHP 7

计算字串出现的次数

PHP 4, PHP 5, PHP 7

方法二: 语言特性-正则匹配

// test

echo 'match:', str_match('xasfsdfbk', 'xasfsdfbk') !== false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'fbk') !== false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'xs') != false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'sfs') !== false ? 'true' : 'false', ';', PHP_EOL;

// code

function str_match($a, $b) {

return preg_match('/' . $b . '/i', $a, $matchs) ? true : false;

}

函数

描述

版本

执行匹配正则表达式

PHP 4, PHP 5, PHP 7

执行一个全局正则表达式匹配

PHP 4, PHP 5, PHP 7

方法三: 语言特性-字符串分割

// test

echo 'match:', str_match('xasfsdfbk', 'xasfsdfbk') !== false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'fbk') !== false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'xs') != false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'sfs') !== false ? 'true' : 'false', ';', PHP_EOL;

// code

function str_match($a, $b) {

return count(explode($b, $a)) >= 2 ? true : false;

}

// strtok 可以么?

// 在分割字符串时,split()与explode()谁快?

函数

描述

版本

标记分割字符串

PHP 4, PHP 5, PHP 7

使用一个字符串分割另一个字符串

PHP 4, PHP 5, PHP 7

用正则表达式将字符串分割到数组中

PHP 4, PHP 5

使用正则表达式分割多字节字符串

PHP 4 >= 4.2.0, PHP 5, PHP 7

通过一个正则表达式分隔字符串

PHP 4, PHP 5, PHP 7

方法四: 很暴力的查找

// test

echo 'match:', str_match('xasfsdfbk', 'xasfsdfbk') !== -1 ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'fbk') !== -1 ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'xs') !== -1 ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'sfs') !== -1 ? 'true' : 'false', ';', PHP_EOL;

// code

function str_match($a, $b) {

if($a == $b) {

return 0;

}

$aArr = str_split($a);

$bArr = str_split($b);

$aLen = count($aArr);

$bLen = count($bArr);

if($bLen > $aLen) {

return -1;

}

$data = [];

$aLastIndex = -1;

$bStartIndex = 0;

for($ai = 0; $ai < $aLen; $ai++) {

$av = $aArr[$ai];

$exists = false;

for($bi = $bStartIndex; $bi < $bLen; $bi++) {

$bv = $bArr[$bi];

if(($aLastIndex == -1 || $ai == ($aLastIndex + 1)) && $av == $bv) {

$exists = true;

break;

}

if ($aLastIndex != -1 && $ai == ($aLastIndex + 1) && $av != $bv) {

break;

}

}

if ($exists) {

$aLastIndex = $ai;

$bStartIndex = $bi + 1;

array_push($data, [

'value' => $av,

'index' => $ai

]);

} else {

$aLastIndex = -1;

$bStartIndex = 0;

$data = [];

}

if ($exists && $bLen == $bStartIndex) {

break;

}

}

if(!empty($data) && count($data) == $bLen) {

$begin = array_shift($data);

return $begin['index'];

} else {

return -1;

}

}

方法五: 朴素算法(暴力查找)

// demo

echo 'match:', str_match('xasfsdfbk', 'xasfsdfbk') !== false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'fbk') !== false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'xs') != false ? 'true' : 'false', ';', PHP_EOL;

echo 'match:', str_match('xasfsdfbk', 'sfs') !== false ? 'true' : 'false', ';', PHP_EOL;

// code

function str_match($a, $b) {

$aArr = str_split($a);

$bArr = str_split($b);

$aLen = count($aArr);

$bLen = count($bArr);

for ($ai = 0; $ai <= $aLen - $bLen; $ai++) {

for ($bi = 0; $bi < $bLen; $bi++) {

if($aArr[$ai + $bi] != $bArr[$bi]) {

break;

}

}

if($bLen == $bi) {

return $ai;

}

}

return false;

}

方法六: 字符串查找算法-Rabin-Karp算法

#include

#include

using namespace std;

#define BASE 256

#define MODULUS 101

void RabinKarp(char t[], char p[])

{

int t_len = strlen(t);

int p_len = strlen(p);

// 哈希滚动之用

int h = 1;

for (int i = 0; i < p_len - 1; i++)

h = (h * BASE) % MODULUS;

int t_hash = 0;

int p_hash = 0;

for (int i = 0; i < p_len; i++)

{

t_hash = (BASE * t_hash + t[i]) % MODULUS;

p_hash = (BASE * p_hash + p[i]) %

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值