面试问题浓缩总结 面试问题浓缩总结
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • 算法

  • 数据结构

    • 线性表
    • 栈和队列
    • 串、数组、广义表
      • 字符串匹配算法
    • 数和二叉树
    • 图
  • 设计模式

  • CMU硕士经典100题

  • 剑指offer

  • 重点手撕代码

  • 程序员面试

  • CodeTop企业题库

  • 笔试题目

  • 算法和数据结构
  • 数据结构
小游
2021-03-21

串、数组、广义表

# 字符串匹配算法

1.BF算法

BF算法是一个古典的算法,算法主要思想如下图所示

img

按顺序一位一位进行比较,如果有一位不匹配,那么原字符串+1

2.KMP算法

KMP最难的地方就在于计算next数组,具体可以参考这篇文章。

https://www.cnblogs.com/SYCstudio/p/7194315.html

next数组的详解

img

func strStr(haystack string, needle string) int {
	// 获取两个字符串的长度
	n := len(haystack)
	m := len(needle)
	if m == 0 {
		return 0
	}
	if n < m {
		return -1
	}
	/*
		计算next数组 这个数组也叫匹配表数组(这个数组的长度就是haystck的长度)

		这里解释一下这个数组的意思 解释之前先理解一下前缀和后缀的概念
		前缀: 例如”Harry”的前缀包括{”H”, ”Ha”, ”Har”, ”Harr”}
		后缀:例如,”Potter”的后缀包括{”r”,”er”,”ter”,”tter”,”otter”}
		这个两个其实一个是正过来一个个的往后加 后缀就是反过来的

		然后我们计算的这个表就是每位所包含的相同前后缀的最长的长度
		对于字符串”ababa”,它的前缀集合为{”a”, ”ab”, ”aba”, ”abab”},它的后缀集合为{”baba”, ”aba”, ”ba”, ”a”}, 两个集合的交集为{”a”, ”aba”},其中最长的元素为”aba”,长度为3。
		我们拿ababa来举例 这个表有5位,第一为就是a的前后缀的最长长度 第二个就是ab 第三就是 aba 第四个是 abab 第五个是 ababa 就这样就算下去

	*/
	next := computeNext(needle)

	q := 0
	// 遍历字符串开始进行匹配
	for i := 0; i < n; i++ {
		// 如果不匹配,并且q不为0,那么我们就让q等于上一位的最短匹配长度
		for q > 0 && haystack[i] != needle[q] {
			q = next[q-1]
		}
		// 如果发现字符串匹配,那么就匹配下一位
		if haystack[i] == needle[q] {
			q++
		}
		// 如果发现q=m 就说明匹配完毕,我们这里计算一下匹配的位置
		if q == m {
			return i + 1 - m
		}
	}
	return -1
}

// 计算next的值
func computeNext(pattern string) []int {
	// 获取next里面的长度
	n := len(pattern)
	// 创建next数组
	next := make([]int, n)
	k := 0
	// 遍历字符串
	for q := 1; q < n; q++ {
		// 这里开始匹配k是从0开始,相当于计算前缀
		// q从1开始相当于计算后缀 这里默认就是开始匹配最长的前后缀
		// 如果不匹配那么最长的前缀就是上一个最长的前缀
		for k > 0 && (pattern[k] != pattern[q]) {
			k = next[k-1]
		}
		// 开始计算
		if pattern[k] == pattern[q] {
			k++
		}
		// 直接把第q为的值赋值进去
		next[q] = k
	}
	return next
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
编辑 (opens new window)
上次更新: 2021/03/25, 23:10:37
栈和队列
数和二叉树

← 栈和队列 数和二叉树→

Theme by Vdoing | Copyright © 2021-2021 小游
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式