- 数据结构与算法
- DSA - 首页
- DSA - 概述
- DSA - 环境设置
- DSA - 算法基础
- DSA - 渐进分析
- 数据结构
- DSA - 数据结构基础
- DSA - 数据结构和类型
- DSA - 数组数据结构
- 链表
- DSA - 链表数据结构
- DSA - 双向链表数据结构
- DSA - 循环链表数据结构
- 栈与队列
- DSA - 栈数据结构
- DSA - 表达式解析
- DSA - 队列数据结构
- 搜索算法
- DSA - 搜索算法
- DSA - 线性搜索算法
- DSA - 二分搜索算法
- DSA - 插值搜索
- DSA - 跳跃搜索算法
- DSA - 指数搜索
- DSA - 斐波那契搜索
- DSA - 子列表搜索
- DSA - 哈希表
- 排序算法
- DSA - 排序算法
- DSA - 冒泡排序算法
- DSA - 插入排序算法
- DSA - 选择排序算法
- DSA - 归并排序算法
- DSA - 希尔排序算法
- DSA - 堆排序
- DSA - 桶排序算法
- DSA - 计数排序算法
- DSA - 基数排序算法
- DSA - 快速排序算法
- 图数据结构
- DSA - 图数据结构
- DSA - 深度优先遍历
- DSA - 广度优先遍历
- DSA - 生成树
- 树数据结构
- DSA - 树数据结构
- DSA - 树的遍历
- DSA - 二叉搜索树
- DSA - AVL树
- DSA - 红黑树
- DSA - B树
- DSA - B+树
- DSA - 伸展树
- DSA - 字典树
- DSA - 堆数据结构
- 递归
- DSA - 递归算法
- DSA - 使用递归实现汉诺塔
- DSA - 使用递归实现斐波那契数列
- 分治法
- DSA - 分治法
- DSA - 最大最小问题
- DSA - Strassen矩阵乘法
- DSA - Karatsuba算法
- 贪心算法
- DSA - 贪心算法
- DSA - 旅行商问题(贪心算法)
- DSA - Prim最小生成树
- DSA - Kruskal最小生成树
- DSA - Dijkstra最短路径算法
- DSA - 地图着色算法
- DSA - 分数背包问题
- DSA - 带截止日期的作业排序
- DSA - 最佳合并模式算法
- 动态规划
- DSA - 动态规划
- DSA - 矩阵链乘法
- DSA - Floyd-Warshall算法
- DSA - 0-1背包问题
- DSA - 最长公共子序列算法
- DSA - 旅行商问题(动态规划)
- 近似算法
- DSA - 近似算法
- DSA - 顶点覆盖算法
- DSA - 集合覆盖问题
- DSA - 旅行商问题(近似算法)
- 随机化算法
- DSA - 随机化算法
- DSA - 随机化快速排序算法
- DSA - Karger最小割算法
- DSA - Fisher-Yates洗牌算法
- DSA有用资源
- DSA - 问答
- DSA - 快速指南
- DSA - 有用资源
- DSA - 讨论
Z算法
用于模式匹配的Z算法
Z算法是一种线性时间字符串匹配算法,用于在字符串中搜索给定模式。其目的是搜索字符串中给定模式的所有出现。Z算法依赖于Z数组来查找模式出现。Z数组是一个整数数组,存储模式与文本任何子字符串之间最长公共前缀的长度。它与字符串的长度相同。
Z算法如何工作?
Z算法通过构建一个名为Z数组的辅助数组来工作,该数组存储给定文本与文本任何子字符串之间最长公共前缀的长度。此数组中的每个索引都存储匹配字符的数量,从第0个索引到当前索引。
Z算法需要以下步骤:
首先,将模式和给定字符串合并在一起。我们还需要在两者之间添加一个特殊字符,该字符不在任何指定的字符串中。假设我们使用美元符号(
$)作为特殊字符。然后,为这个新创建的字符串构建Z数组。
现在,检查Z数组的每个索引以查找其值是否与正在搜索的模式的长度匹配。如果值和长度匹配,则将模式标记为已找到。
在最后一步中,从模式长度+1中减去索引号,这将导致模式的索引。
下图说明了上述方法:
让我们了解输入输出场景:
Input: Main String: "ABAAABCDBBABCDDEBCABC" Pattern: "ABC" Output: Pattern found at position: 4 Pattern found at position: 10 Pattern found at position: 18
在上述场景中,我们正在主字符串“ABAAABCDBBABCDDEBCABC”中查找模式“ABC”。我们将检查主字符串中的每个位置并记下我们在哪里找到匹配项。我们在位置4、10和18找到了模式“ABC”。
示例
以下是演示各种编程语言中Z算法的示例:
#include <stdio.h>
#include <string.h>
// function to fill Z array
void fillZArray(const char* conStr, int zArr[]) {
int n = strlen(conStr);
int windLeft, windRight, k;
// Initialize the window size to 0
windLeft = windRight = 0;
// iterating over the characters of the new string
for (int i = 1; i < n; i++) {
// checking if current index is greater than right bound of window
if (i > windRight) {
// reset the window size to 0 and position it at the current index
windLeft = windRight = i;
// extend right bound of window as long as characters match
while (windRight < n && conStr[windRight - windLeft] == conStr[windRight]) {
windRight++;
}
// setting the Z value for the current index
zArr[i] = windRight - windLeft;
// decrementing right bound
windRight--;
} else {
// calculating corresponding index in window
k = i - windLeft;
// if Z value at corresponding index is less than remaining interval
if (zArr[k] < windRight - i + 1) {
zArr[i] = zArr[k];
} else {
// reset left bound of window to current index
windLeft = i;
// extend right bound of window as long as characters match
while (windRight < n && conStr[windRight - windLeft] == conStr[windRight]) {
windRight++;
}
// Setting the Z value for the current index
zArr[i] = windRight - windLeft;
// Decrement the right bound of the window
windRight--;
}
}
}
}
// function to implement the Z algorithm for pattern searching
void zAlgorithm(const char* mainString, const char* pattern, int array[], int *index) {
// concatenate the pattern, a special character, and the main string
char concatedStr[strlen(mainString) + strlen(pattern) + 1];
strcpy(concatedStr, pattern);
strcat(concatedStr, "$");
strcat(concatedStr, mainString);
int patLen = strlen(pattern);
int len = strlen(concatedStr);
// Initialize the Z array
int zArr[len];
// Fill the Z array
fillZArray(concatedStr, zArr);
// iterate over the Z array
for (int i = 0; i < len; i++) {
// if Z value equals length of the pattern, the pattern is found
if (zArr[i] == patLen) {
(*index)++;
array[(*index)] = i - patLen - 1;
}
}
}
int main() {
const char* mainString = "ABAAABCDBBABCDDEBCABC";
const char* pattern = "ABC";
// Initialize the location array and the index
int locArray[strlen(mainString)];
int index = -1;
// Calling the Z algorithm function
zAlgorithm(mainString, pattern, locArray, &index);
// to print the result
for (int i = 0; i <= index; i++) {
printf("Pattern found at position: %d\n", locArray[i]);
}
return 0;
}
输出
Pattern found at position: 4 Pattern found at position: 10 Pattern found at position: 18
#include<iostream>
using namespace std;
// function to fill Z array
void fillZArray(string conStr, int zArr[]) {
int n = conStr.size();
int windLeft, windRight, k;
// initially window size is 0
windLeft = windRight = 0;
// iterating over the characters of the new string
for(int i = 1; i < n; i++) {
// checking if current index is greater than right bound of window
if(i > windRight) {
// reset the window size to 0 and position it at the current index
windLeft = windRight = i;
// extend right bound of window as long as characters match
while(windRight < n && conStr[windRight-windLeft] == conStr[windRight]) {
windRight++;
}
// setting the Z value for the current index
zArr[i] = windRight-windLeft;
// decrementing right bound
windRight--;
}else {
// calculating corresponding index in window
k = i-windLeft;
// if Z value at corresponding index is less than remaining interval
if(zArr[k] < windRight-i+1)
zArr[i] = zArr[k];
else {
// reset left bound of window to current index
windLeft = i;
// extend right bound of window as long as characters match
while(windRight < n && conStr[windRight - windLeft] == conStr[windRight]) {
windRight++;
}
// Setting the Z value for the current index
zArr[i] = windRight - windLeft;
// Decrement the right bound of the window
windRight--;
}
}
}
}
// function to implement the Z algorithm for pattern searching
void zAlgorithm(string mainString, string pattern, int array[], int *index) {
// concatenate the pattern, a special character, and the main string
string concatedStr = pattern + "$" + mainString;
int patLen = pattern.size();
int len = concatedStr.size();
// Initialize the Z array
int zArr[len];
// Fill the Z array
fillZArray(concatedStr, zArr);
// iterate over the Z array
for(int i = 0; i<len; i++) {
// if Z value equals length of the pattern, the pattern is found
if(zArr[i] == patLen) {
(*index)++;
array[(*index)] = i - patLen -1;
}
}
}
int main() {
string mainString = "ABAAABCDBBABCDDEBCABC";
string pattern = "ABC";
// Initialize the location array and the index
int locArray[mainString.size()];
int index = -1;
// Calling the Z algorithm function
zAlgorithm(mainString, pattern, locArray, &index);
// to print the result
for(int i = 0; i <= index; i++) {
cout << "Pattern found at position: " << locArray[i]<<endl;
}
}
输出
Pattern found at position: 4 Pattern found at position: 10 Pattern found at position: 18
public class ZAlgorithm {
// method to fill Z array
public static void fillZArray(String conStr, int[] zArr) {
int n = conStr.length();
int windLeft, windRight, k;
// initially window size is 0
windLeft = windRight = 0;
// iterating over the characters of the new string
for (int i = 1; i < n; i++) {
// checking if current index is greater than right bound of window
if (i > windRight) {
// reset the window size to 0 and position it at the current index
windLeft = windRight = i;
while (windRight < n && conStr.charAt(windRight - windLeft) == conStr.charAt(windRight)) {
windRight++;
}
// setting the Z value for the current index
zArr[i] = windRight - windLeft;
windRight--;
} else {
k = i - windLeft;
if (zArr[k] < windRight - i + 1)
zArr[i] = zArr[k];
else {
windLeft = i;
while (windRight < n && conStr.charAt(windRight - windLeft) == conStr.charAt(windRight)) {
windRight++;
}
zArr[i] = windRight - windLeft;
windRight--;
}
}
}
}
// method to implement the Z algorithm for pattern searching
public static void zAlgorithm(String mainString, String pattern, int[] array) {
// concatenate the pattern, a special character, and the main string
String concatedStr = pattern + "$" + mainString;
int patLen = pattern.length();
int len = concatedStr.length();
// Initialize the Z array
int[] zArr = new int[len];
// Fill the Z array
fillZArray(concatedStr, zArr);
int index = -1;
// iterate over the Z array
for (int i = 0; i < len; i++) {
// if Z value equals length of the pattern, the pattern is found
if (zArr[i] == patLen) {
index++;
array[index] = i - patLen - 1;
}
}
// Print the results
for (int i = 0; i <= index; i++) {
System.out.println("Pattern found at position: " + array[i]);
}
}
public static void main(String[] args) {
String mainString = "ABAAABCDBBABCDDEBCABC";
String pattern = "ABC";
// Initialize the location array and the index
int[] locArray = new int[mainString.length()];
// Calling the Z algorithm method
zAlgorithm(mainString, pattern, locArray);
}
}
输出
Pattern found at position: 4 Pattern found at position: 10 Pattern found at position: 18
# function to fill Z array
def fillZArray(conStr, zArr):
n = len(conStr)
windLeft, windRight, k = 0, 0, 0
# iterating over the characters of the new string
for i in range(1, n):
if i > windRight:
windLeft, windRight = i, i
while windRight < n and conStr[windRight - windLeft] == conStr[windRight]:
windRight += 1
zArr[i] = windRight - windLeft
windRight -= 1
else:
k = i - windLeft
if zArr[k] < windRight - i + 1:
zArr[i] = zArr[k]
else:
windLeft = i
while windRight < n and conStr[windRight - windLeft] == conStr[windRight]:
windRight += 1
zArr[i] = windRight - windLeft
windRight -= 1
# function to implement the Z algorithm for pattern searching
def zAlgorithm(mainString, pattern, array):
concatedStr = pattern + "$" + mainString
patLen = len(pattern)
length = len(concatedStr)
zArr = [0] * length
fillZArray(concatedStr, zArr)
index = -1
for i in range(length):
if zArr[i] == patLen:
index += 1
array[index] = i - patLen - 1
return index, array
def main():
mainString = "ABAAABCDBBABCDDEBCABC"
pattern = "ABC"
locArray = [0] * len(mainString)
index, locArray = zAlgorithm(mainString, pattern, locArray)
for i in range(index + 1):
print("Pattern found at position:", locArray[i])
if __name__ == "__main__":
main()
输出
Pattern found at position: 4 Pattern found at position: 10 Pattern found at position: 18
Z算法的复杂度
Z算法用于模式搜索,其运行时间为线性时间。因此,其时间复杂度为O(m + n),其中n是被搜索字符串的长度,m是被搜索模式的长度。
广告