Algorithm2---字符串匹配算法

BF 暴力匹配

代码实现

func Search(p string,t string)int{
	m := len(p)
	n := len(t)
	for i:=0;i<n-m;i++{
		j := 0
		for j=0;j<m;j++{
			if p[j] != t[i+j]{break}
		}
		//全都匹配
		if j == m{
			return i
		}
	}
	return -1
}

BM 算法

特点是当不匹配的时候 一次性可以跳过不止一个字符
那它是利用了什么特性去 排除尽可能多的无法匹配的位置 呢?

  • bad-character shift 坏字符串规则:移动的位数 = 坏字符在模式串p中的位置-坏字符串在模式串中最右出现的位置
  • good-suffix shift 好后缀规则:后移位数 = 好后缀在模式串中的位置-好后缀在模式串上一次出现的位置,

KMP 算法

先在开头约定,本文用pat表示模式串,长度为M,txt表示文本串,长度为N。KMP 算法是在txt中查找子串pat,如果存在,返回这个子串的起始索引,否则返回 -1。

为什么我认为 KMP 算法就是个动态规划问题呢?

KMP 算法永不回退txt的指针i,不走回头路(不会重复扫描txt),而是借助dp数组中储存的信息把pat移到正确的位置继续匹配,时间复杂度只需 O(N),用空间换时间,所以我认为它是一种动态规划算法。

计算这个dp数组,只和pat串有关

代码实现

// 这个方法没搞懂
var dp [][]int
var p string
func Search(t string)int{
	m := len(p)
	n := len(t)
	//p的初始态为0
	j := 0
	for i:=0;i<n;i++{
		//计算p的下一个状态
		j = dp[j][t[i]]
		if j == m{
			return i-m+1
		}
	}
	return -1
}

func KMP(p string){
	m := len(p)
	//dp[状态][字符]=下个状态
	dp[0][p[0]] = 1
	//影子状态X初始为0
	x := 0
	//构建状态转移方程
	for j:=1;j<m;j++{
		for c:=0;c<256;c++{
			dp[j][c] = dp[x][c]
		}
		dp[j][p[j]] = j+1
		//更新影子状态
		x = dp[x][p[j]]
	}
}

书上介绍的解题思路

package main

import "fmt"

func GetNext(T string, next []int){
	length := len(T)
	i:=1
	j:=0
	next[0] = 0
	for i<length{
		if j==0 || T[i-1]==T[j-1]{ //T[i]表示后缀字符  T[j]表示前缀字符
			if T[i]!=T[j]{
				next[i]=j+1
			}else {
				next[i] = next[j]
			}
			j++
			i++
		}else {
			j = next[j-1]
		}
	}
}
// 返回子串T在主串S中第pos个字符之后的位置。若不存在则函数返回值为0
func IndexKMP(S string,T string,pos int)int{
	lengthS := len(S)
	lengthT := len(T)
	i := pos  //用于主串S当前位置下标值
	j := 0   //用于子串T当前位置下标值
	next := []int{0,0,0,0,0,0,0,0,0}
	GetNext(T,next)
	fmt.Println(next,i,j)
	for i<lengthS && j<lengthT{
		if j==0 || S[i] == T[j]{
			//fmt.Println(S[i],T[j])
			i++
			j++
		}else {
			j = next[j-1] //j退回合适的位置
		}
	}
	//fmt.Println(j ,lengthT)
	if j>lengthT-1{
		return i-lengthT
	}else {
		return 0
	}
}
func main(){
	S := "abvvvabcabc"
	//T := "bbbbbbbba"
	T := "ababaaaba"
	res := IndexKMP(S,T,0)
	fmt.Println(res)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值