Levenshtein 两个文件的距离花费了太多时间
Levenshtein Distance on two files taking too much time
我是编程新手,我正在构建一个文件相似性查找器,它可以找出两个文件的相似程度。 到目前为止,我将文件存储为两个字符串,然后使用 levenshtein 距离来找出文件的相似程度。
问题是,没有 levenshtein 距离的执行时间为 206ms,这是由于文件到字符串的转换。 当我使用levenshtein距离时,执行时间高达19504ms
将文件转换为字符串所花费的时间几乎是 95 倍,这使这成为我项目中的瓶颈
任何帮助将不胜感激 我对C,C++和Python很满意。如果您能指出我的任何来源,我将不胜感激
以下是我用于计算列文施泰因距离的函数的C++代码:
//LEVENSHTEIN
int levenshtein(std::string a, std::string b){
int len_a = a.length();
int len_b = b.length();
int d[len_a + 1][len_b+1];
for(int i = 0; i < len_a + 1; i++)
d[i][0] = i;
for(int j = 0; j < len_b + 1; j++)
d[0][j] = j;
for(int i = 1; i < len_a + 1; i++){
for(int j = 1; j < len_b + 1; j++){
if(a[i - 1] == b[j - 1]){
d[i][j] = d[i - 1][j - 1];
}
else{
d[i][j] = 1 + min(min(d[i][j-1],d[i-1][j]),d[i-1][j-1]);
}
}
}
int answer = d[len_a][len_b];
return answer;
}
我只需要比较两个文件,而不是更多。我读到了 trie 在 levenshtein 中的用法,但这对于将多个字符串与源代码进行比较很有用。除此之外,我没有太多的运气
我将向您展示一个C++解决方案。使用的语言是C++17。编译器是MS Visual Studio Community 2019。在启用所有优化的发布模式下编译。
我用"Lorem ipsum sum总和"生成器创建了两个文件,每个文件有1000个单词。每个文件的文件大小为 ~6kB。
结果在眨眼间就出来了。
我正在使用略微修改的levensthein函数,并且还使用了更具可读性的变量名称。我不使用 VLA(可变长度数组(,因为这在C++无效。我改用std::vector
,它具有更出色的功能。
总的来说,我们可以看到驱动程序代码。首先,我们打开 2 个输入文件,并检查它们是否可以打开。如果没有,我们会显示一条错误消息并退出程序。
然后,我们使用std::string
范围构造函数和std::istreambuf_iterator
将 2 个文本文件读入 2 个字符串。我不知道有什么更简单的方法来将完整的文本文件读取到std::string
中。
然后我们打印列文森距离的结果。
请参阅下面的代码:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <iterator>
// Distance between 2 strings
size_t levensthein(const std::string& string1, const std::string& string2)
{
// First get the string lengths
const size_t lengthString1{ string1.size() };
const size_t lengthString2{ string2.size() };
// If one of the string length is 0, then return the length of the other
// This results in 0, if both lengths are 0
if (lengthString1 == 0) return lengthString2;
if (lengthString2 == 0) return lengthString1;
// Initialize substitition cost vector
std::vector<size_t> substitutionCost(lengthString2 + 1);
std::iota(substitutionCost.begin(), substitutionCost.end(), 0);
// Calculate substitution cost
for (size_t indexString1{}; indexString1 < lengthString1; ++indexString1) {
substitutionCost[0] = indexString1 + 1;
size_t corner{ indexString1 };
for (size_t indexString2{}; indexString2 < lengthString2; ++indexString2) {
size_t upper{ substitutionCost[indexString2 + 1] };
if (string1[indexString1] == string2[indexString2]) {
substitutionCost[indexString2 + 1] = corner;
}
else {
const size_t temp = std::min(upper, corner);
substitutionCost[indexString2 + 1] = std::min(substitutionCost[indexString2], temp) + 1;
}
corner = upper;
}
}
return substitutionCost[lengthString2];
}
// Put in your filenames here
const std::string fileName1{ "text1.txt" };
const std::string fileName2{ "text2.txt" };
int main() {
// Open first file and check, if it could be opened
if (std::ifstream file1Stream{ fileName1 }; file1Stream) {
// Open second file and check, if it could be opened
if (std::ifstream file2Stream{ fileName2 }; file2Stream) {
// Both files are open now, read them into strings
std::string stringFile1(std::istreambuf_iterator<char>(file1Stream), {});
std::string stringFile2(std::istreambuf_iterator<char>(file2Stream), {});
// Show Levenstehin distance on screen
std::cout << "Levensthein distance is: " << levensthein(stringFile1, stringFile2) << 'n';
}
else {
std::cerr << "n*** Error. Could not open input file '" << fileName2 << "'n";
}
}
else {
std::cerr << "n*** Error. Could not open input file '" << fileName1 << "'n";
}
return 0;
}
有一个名为 nltk 的包。看看吧。
from nltk import distance
print(distance.edit_distance('aa', 'ab'))
输出:
1
- C++为构建时间获取QDateTime的可靠方法
- 从持续时间构造std::chrono::system_clock::time_point
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- while循环中while循环的时间复杂度是多少
- 使用简单类型列表实现的指数编译时间.为什么
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 在已经使用Git的情况下减少编译时间
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何将包含epoch时间的十六进制字符串转换为time_t
- 如何修复此错误:未定义对"距离(浮点数,浮点数,浮点数,浮点数,浮点数)"的引用
- 从文本文件中读取时钟时间和事件时间并进行处理
- 具有未知值时的时间复杂性
- 如何减少花费的时间
- C++在变量给定的指定时间内关闭电脑
- rcpp函数中的清理时间很长
- C++:floor unix时间戳到UTC月份
- 如何在c++中录制具有精确帧时间戳的视频
- 如何使用发送数据包所花费的时间计算两个节点之间的距离?
- Levenshtein 两个文件的距离花费了太多时间
- 是否有具有对数时间插入、删除和查找(带距离)的排序数据结构