元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
算法基础
▶
复杂度分析
时间复杂度
空间复杂度
渐进符号
▶
算法思想
分治法
贪心算法
回溯法
概率算法
枚举算法
递推算法
递归算法
动态规划
分支限界法
模拟算法
▶
算法分析
正确性证明
性能优化
算法比较
▶
搜索算法
▶
基本搜索
顺序搜索
二分搜索
插值搜索
▶
图搜索
深度优先搜索
广度优先搜索
启发式搜索
▶
高级搜索
双向搜索
A*算法
模式匹配
▶
排序算法
▶
比较类排序
冒泡排序
快速排序
归并排序
插入排序
选择排序
▶
非比较类排序
计数排序
基数排序
桶排序
▶
高级排序
堆排序
希尔排序
外部排序
拓扑排序
▶
图论算法
▶
图的表示
邻接矩阵
邻接表
边集数组
▶
最短路径
Dijkstra算法
Floyd算法
Bellman-Ford算法
最短路径概述
▶
生成树
Prim算法
Kruskal算法
并查集
最小生成树
▶
图的连通性
强连通分量
割点与桥
双连通分量
欧拉路径
▶
动态规划
▶
基础概念
最优子结构
重叠子问题
状态转移方程
▶
经典问题
背包问题
最长公共子序列
编辑距离
▶
优化技巧
空间优化
状态压缩
区间动态规划
▶
字符串算法
▶
字符串匹配
KMP算法
Boyer-Moore算法
Sunday算法
▶
字符串处理
字典树
后缀数组
字符串哈希
▶
压缩算法
游程编码
Huffman编码
LZ77算法
发布时间:
2025-03-21 18:30
↑
☰
# 模式匹配 模式匹配(Pattern Matching)是一种在文本中查找特定模式的搜索算法。它在文本处理、编译器设计、生物信息学等领域有广泛应用。本文将介绍几种常见的模式匹配算法及其实现。 ## 基本概念 1. 文本串(Text):待搜索的主字符串 2. 模式串(Pattern):要查找的目标字符串 3. 匹配位置:模式串在文本串中出现的位置 4. 失配:当前比较的字符不相等的情况 ## 朴素字符串匹配 ### 基本原理 朴素字符串匹配(Naive String Matching)是最简单的模式匹配算法: 1. 从文本串的第一个字符开始 2. 尝试匹配模式串的每个字符 3. 如果失配,文本串向右移动一位 4. 重复步骤2-3,直到找到匹配或到达文本串末尾 ### 代码实现 ```python def naive_search(text, pattern): n = len(text) m = len(pattern) positions = [] for i in range(n - m + 1): match = True for j in range(m): if text[i + j] != pattern[j]: match = False break if match: positions.append(i) return positions # 使用示例 text = "AABAACAADAABAAABAA" pattern = "AABA" result = naive_search(text, pattern) print(f"模式 '{pattern}' 在文本中的位置: {result}") ``` ## KMP算法 ### 基本原理 KMP(Knuth-Morris-Pratt)算法通过预处理模式串,构建部分匹配表(next数组),在失配时能够跳过一些不必要的比较: 1. 预处理模式串,构建next数组 2. 利用next数组在失配时进行快速移动 3. 避免重复比较已知匹配的部分 ### 代码实现 ```python def build_next(pattern): m = len(pattern) next = [0] * m j = 0 for i in range(1, m): while j > 0 and pattern[i] != pattern[j]: j = next[j - 1] if pattern[i] == pattern[j]: j += 1 next[i] = j return next def kmp_search(text, pattern): if not pattern: return [] next = build_next(pattern) positions = [] j = 0 # 模式串的位置 for i in range(len(text)): while j > 0 and text[i] != pattern[j]: j = next[j - 1] if text[i] == pattern[j]: j += 1 if j == len(pattern): positions.append(i - j + 1) j = next[j - 1] return positions # 使用示例 text = "AABAACAADAABAAABAA" pattern = "AABA" result = kmp_search(text, pattern) print(f"模式 '{pattern}' 在文本中的位置: {result}") ``` ## Boyer-Moore算法 ### 基本原理 Boyer-Moore算法是一种高效的字符串搜索算法,它通过以下两个规则来实现快速跳过: 1. 坏字符规则:当发生失配时,移动模式串使失配字符对齐 2. 好后缀规则:利用已匹配的后缀信息进行移动 ### 代码实现 ```python def build_bad_char(pattern): # 构建坏字符表 bad_char = {} for i in range(len(pattern)): bad_char[pattern[i]] = i return bad_char def boyer_moore_search(text, pattern): if not pattern: return [] # 构建坏字符表 bad_char = build_bad_char(pattern) positions = [] m = len(pattern) n = len(text) i = 0 # 文本串中的位置 while i <= n - m: j = m - 1 # 从模式串的最后一个字符开始比较 # 从右向左比较字符 while j >= 0 and pattern[j] == text[i + j]: j -= 1 if j < 0: # 找到匹配 positions.append(i) i += 1 else: # 使用坏字符规则计算移动距离 skip = j - bad_char.get(text[i + j], -1) i += max(1, skip) return positions # 使用示例 text = "AABAACAADAABAAABAA" pattern = "AABA" result = boyer_moore_search(text, pattern) print(f"模式 '{pattern}' 在文本中的位置: {result}") ``` ## Sunday算法 ### 基本原理 Sunday算法是一种简单高效的字符串匹配算法,它通过考察主串中参与匹配的子串的下一位字符来决定移动距离: 1. 对齐文本串和模式串 2. 从左到右比较字符 3. 如果失配,查看主串中参与匹配的子串的下一位字符 4. 根据下一位字符在模式串中最右出现的位置计算移动距离 ### 代码实现 ```python def sunday_search(text, pattern): if not pattern: return [] # 构建移动表 move = {} for i in range(len(pattern)): move[pattern[i]] = len(pattern) - i positions = [] n = len(text) m = len(pattern) i = 0 while i <= n - m: match = True for j in range(m): if text[i + j] != pattern[j]: match = False break if match: positions.append(i) if i + m >= n: break # 计算移动距离 next_char = text[i + m] i += move.get(next_char, m + 1) return positions # 使用示例 text = "AABAACAADAABAAABAA" pattern = "AABA" result = sunday_search(text, pattern) print(f"模式 '{pattern}' 在文本中的位置: {result}") ``` ## 性能比较 ### 时间复杂度 | 算法 | 预处理 | 匹配 | 最坏情况 | |------|--------|------|----------| | 朴素算法 | O(1) | O(mn) | O(mn) | | KMP | O(m) | O(n) | O(n) | | Boyer-Moore | O(m + σ) | O(n) | O(mn) | | Sunday | O(m) | O(n) | O(mn) | 其中: - n 是文本串长度 - m 是模式串长度 - σ 是字符集大小 ### 空间复杂度 | 算法 | 空间复杂度 | |------|------------| | 朴素算法 | O(1) | | KMP | O(m) | | Boyer-Moore | O(m + σ) | | Sunday | O(σ) | ## 应用场景 1. 文本编辑器的查找功能 2. 生物序列比对 3. 编译器的词法分析 4. 网络入侵检测 5. 垃圾邮件过滤 ## 实际应用示例 ### 1. 简单文本编辑器 ```python class TextEditor: def __init__(self): self.text = "" def insert(self, text): self.text += text def find_all(self, pattern): # 使用KMP算法查找所有匹配 positions = kmp_search(self.text, pattern) return positions def replace(self, pattern, replacement): positions = self.find_all(pattern) # 从后向前替换,避免位置变化 for pos in reversed(positions): self.text = (self.text[:pos] + replacement + self.text[pos + len(pattern):]) # 使用示例 editor = TextEditor() editor.insert("Hello world! Hello Python!") print("原文本:", editor.text) pattern = "Hello" positions = editor.find_all(pattern) print(f"找到 '{pattern}' 的位置:", positions) editor.replace("Hello", "Hi") print("替换后:", editor.text) ``` ### 2. DNA序列匹配 ```python class DNAMatcher: def __init__(self, sequence): self.sequence = sequence def find_pattern(self, pattern): # 使用Boyer-Moore算法查找模式 return boyer_moore_search(self.sequence, pattern) def count_pattern(self, pattern): positions = self.find_pattern(pattern) return len(positions) def find_repeats(self, min_length=3): repeats = {} n = len(self.sequence) for length in range(min_length, n//2 + 1): for i in range(n - length + 1): pattern = self.sequence[i:i+length] count = self.count_pattern(pattern) if count > 1: repeats[pattern] = count return repeats # 使用示例 dna = DNAMatcher("ACGTACGTACGTACGT") pattern = "ACGT" positions = dna.find_pattern(pattern) print(f"DNA序列中 '{pattern}' 的位置:", positions) repeats = dna.find_repeats() print("重复序列:", repeats) ``` ## 优化技巧 1. 字符集优化 ```python def optimize_for_charset(pattern, charset): # 根据实际字符集大小选择算法 if len(charset) < 30: return "KMP" elif len(charset) < 100: return "Boyer-Moore" else: return "Sunday" ``` 2. 多模式匹配 ```python from collections import defaultdict def multi_pattern_search(text, patterns): # 使用字典树(Trie)存储多个模式 trie = defaultdict(dict) for i, pattern in enumerate(patterns): current = trie for c in pattern: if c not in current: current[c] = defaultdict(dict) current = current[c] current['#'] = i # 在文本中查找所有模式 results = defaultdict(list) n = len(text) for i in range(n): current = trie j = i while j < n and text[j] in current: current = current[text[j]] if '#' in current: pattern_index = current['#'] results[patterns[pattern_index]].append(i) j += 1 return results ``` 3. 大文本处理 ```python def process_large_text(filename, pattern, chunk_size=1024): positions = [] offset = 0 with open(filename, 'r') as f: while True: chunk = f.read(chunk_size) if not chunk: break # 处理chunk之间的边界情况 if offset > 0: chunk = prev_chunk[-len(pattern)+1:] + chunk chunk_positions = kmp_search(chunk, pattern) positions.extend([p + offset for p in chunk_positions]) prev_chunk = chunk offset += len(chunk) return positions ``` ## 总结 模式匹配算法是字符串处理中的基础算法,不同的算法有其特定的优势和适用场景: 1. 朴素算法:实现简单,适用于短文本或模式 2. KMP算法:性能稳定,适用于一般场景 3. Boyer-Moore算法:在实际应用中常常是最快的 4. Sunday算法:实现简单且效率高 在实际应用中,应根据具体需求(文本特征、模式长度、字符集大小等)选择合适的算法。同时,可以通过优化技巧来提高算法的性能,如字符集优化、多模式匹配等。