KMP算法详解与C++实现:高效字符串匹配技术

版权申诉
0 下载量 90 浏览量 更新于2024-10-07 1 收藏 674B RAR 举报
资源摘要信息:"KMP算法详解及其实例" KMP算法(Knuth-Morris-Pratt)是一种高效的字符串匹配算法,由Donald Knuth、Vaughan Pratt和James H. Morris共同发明,用于在一个文本字符串S内查找一个词W的出现位置。该算法的核心在于避免了不必要的比较,通过一个预处理过程对模式串(待查找的词)进行分析,构建一个部分匹配表(也称为前缀函数或失败函数),以实现O(n+m)的时间复杂度,其中n是文本串的长度,m是模式串的长度。 在KMP算法中,部分匹配表用于记录模式串中前缀和后缀的最长公共元素长度,这对于算法的效率至关重要。一旦在文本串的匹配过程中出现不匹配,算法会利用该表跳过尽可能多的字符,而不是每次都从头开始匹配,这样显著提高了匹配效率。 KMP算法的C++源码通常会包含以下几个主要函数或部分: 1. 构造部分匹配表的函数:此函数计算模式串的前缀函数数组,该数组记录了模式串前缀的最长相等前后缀的长度,数组的每个元素对应模式串的一个字符。 2. KMP算法主函数:该函数读取文本串和模式串,使用已构造的部分匹配表来执行模式匹配。当遇到不匹配的字符时,根据部分匹配表中的信息决定如何移动模式串,以跳过已经匹配的部分。 3. 辅助函数:可能会包含一些辅助功能,如读取字符串、打印结果等。 KMP算法的核心思想可以用以下几个关键点来概括: - 避免从头开始匹配:当字符不匹配时,算法不会将模式串的指针重置为0,而是根据部分匹配表进行适当移动。 - 部分匹配表的构建:这是算法效率的关键,它决定了在不匹配发生时模式串可以移动多远。 - 时间复杂度:KMP算法的时间复杂度为O(n),n是文本串的长度,因为每个字符最多被访问两次(一次在主函数中,一次在构造部分匹配表的函数中)。 在实际应用中,KMP算法广泛应用于文本编辑器的查找功能、搜索引擎的文本搜索、生物信息学中的基因序列分析等领域。由于其高效的性能和对重复匹配的智能处理,KMP算法被计算机科学教育广泛采用作为算法学习的经典案例。 KMP算法的C++实现通常会用到以下数据结构和函数: - 字符数组(或字符串类):用于存储文本串和模式串。 - 循环或递归:用于构建部分匹配表。 - 数组或向量:用于存储部分匹配表,通常命名为next数组或pi数组。 - 循环:用于遍历文本串并执行匹配过程。 下面是一个简单的KMP算法C++源码示例,这个示例仅用于演示算法核心思想,实际应用中可能需要更多的辅助功能和健壮性处理: ```cpp #include <iostream> #include <vector> #include <string> void computeLPSArray(const std::string& pat, std::vector<int>& lps) { int len = 0; // length of the previous longest prefix suffix int i = 1; lps[0] = 0; // lps[0] is always 0 while (i < pat.size()) { if (pat[i] == pat[len]) { len++; lps[i] = len; i++; } else { if (len != 0) { len = lps[len - 1]; } else { lps[i] = 0; i++; } } } } void KMPSearch(const std::string& pat, const std::string& txt) { int M = pat.size(); int N = txt.size(); std::vector<int> lps(M); computeLPSArray(pat, lps); int i = 0; // index for txt[] int j = 0; // index for pat[] while (i < N) { if (pat[j] == txt[i]) { j++; i++; } if (j == M) { std::cout << "Found pattern at index " << i - j << std::endl; j = lps[j - 1]; } else if (i < N && pat[j] != txt[i]) { if (j != 0) j = lps[j - 1]; else i = i + 1; } } } int main() { std::string txt = "ABABDABACDABABCABAB"; std::string pat = "ABABCABAB"; KMPSearch(pat, txt); return 0; } ``` 上述代码中,`computeLPSArray`函数负责构建部分匹配表,`KMPSearch`函数则是执行KMP搜索的核心函数。在`main`函数中,我们定义了文本串和模式串,并调用`KMPSearch`函数进行匹配。 KMP算法在处理大规模数据和实现高性能字符串匹配时具有明显的优势,因此理解并掌握该算法的实现原理对于任何需要进行字符串处理的程序员来说都是非常有价值的。

import numpy import numpy as np import matplotlib.pyplot as plt import math import torch from torch import nn from torch.utils.data import DataLoader, Dataset import os os.environ['KMP_DUPLICATE_LIB_OK']='True' dataset = [] for data in np.arange(0, 3, .01): data = math.sin(data * math.pi) dataset.append(data) dataset = np.array(dataset) dataset = dataset.astype('float32') max_value = np.max(dataset) min_value = np.min(dataset) scalar = max_value - min_value print(scalar) dataset = list(map(lambda x: x / scalar, dataset)) def create_dataset(dataset, look_back=3): dataX, dataY = [], [] for i in range(len(dataset) - look_back): a = dataset[i:(i + look_back)] dataX.append(a) dataY.append(dataset[i + look_back]) return np.array(dataX), np.array(dataY) data_X, data_Y = create_dataset(dataset) train_X, train_Y = data_X[:int(0.8 * len(data_X))], data_Y[:int(0.8 * len(data_Y))] test_X, test_Y = data_Y[int(0.8 * len(data_X)):], data_Y[int(0.8 * len(data_Y)):] train_X = train_X.reshape(-1, 1, 3).astype('float32') train_Y = train_Y.reshape(-1, 1, 3).astype('float32') test_X = test_X.reshape(-1, 1, 3).astype('float32') train_X = torch.from_numpy(train_X) train_Y = torch.from_numpy(train_Y) test_X = torch.from_numpy(test_X) class RNN(nn.Module): def __init__(self, input_size, hidden_size, output_size=1, num_layer=2): super(RNN, self).__init__() self.input_size = input_size self.hidden_size = hidden_size self.output_size = output_size self.num_layer = num_layer self.rnn = nn.RNN(input_size, hidden_size, batch_first=True) self.linear = nn.Linear(hidden_size, output_size) def forward(self, x): out, h = self.rnn(x) out = self.linear(out[0]) return out net = RNN(3, 20) criterion = nn.MSELoss(reduction='mean') optimizer = torch.optim.Adam(net.parameters(), lr=1e-2) train_loss = [] test_loss = [] for e in range(1000): pred = net(train_X) loss = criterion(pred, train_Y) optimizer.zero_grad() # 反向传播 loss.backward() optimizer.step() if (e + 1) % 100 == 0: print('Epoch:{},loss:{:.10f}'.format(e + 1, loss.data.item())) train_loss.append(loss.item()) plt.plot(train_loss, label='train_loss') plt.legend() plt.show()请适当修改代码,并写出预测值和真实值的代码

2023-06-09 上传