使用列文施泰因距离在字典中查找朋友的朋友
Finding Friend of Friend in a Dictionary using Levenshtein distance
以下是我正在尝试做的事情。两个词W1
和W2
是朋友,如果这些词的Levenshtein distance
是1。我也应该找到所有朋友的朋友。我试图用Bk-Tree做同样的事情。它适用于小尺寸词典(词典每行仅包含一个单词(但是对于更大的字典,它正在严重减慢并运行一个多小时仍然没有结果。
以下是我到目前为止的代码
#include <string>
#include <vector>
#include <queue>
#include <fstream>
#include <iostream>
#include <algorithm>
class BkTree {
public:
BkTree();
~BkTree();
void insert(std::string m_item);
void get_friends(std::string center, std::deque<std::string>& friends);
private:
size_t EditDistance( const std::string &s, const std::string &t );
struct Node {
std::string m_item;
size_t m_distToParent;
Node *m_firstChild;
Node *m_nextSibling;
Node(std::string x, size_t dist);
bool visited;
~Node();
};
Node *m_root;
int m_size;
protected:
};
BkTree::BkTree() {
m_root = NULL;
m_size = 0;
}
BkTree::~BkTree() {
if( m_root )
delete m_root;
}
BkTree::Node::Node(std::string x, size_t dist) {
m_item = x;
m_distToParent = dist;
m_firstChild = m_nextSibling = NULL;
visited = false;
}
BkTree::Node::~Node() {
if( m_firstChild )
delete m_firstChild;
if( m_nextSibling )
delete m_nextSibling;
}
void BkTree::insert(std::string m_item) {
if( !m_root ){
m_size = 1;
m_root = new Node(m_item, -1);
return;
}
Node *t = m_root;
while( true ) {
size_t d = EditDistance( t->m_item, m_item );
if( !d )
return;
Node *ch = t->m_firstChild;
while( ch ) {
if( ch->m_distToParent == d ) {
t = ch;
break;
}
ch = ch->m_nextSibling;
}
if( !ch ) {
Node *newChild = new Node(m_item, d);
newChild->m_nextSibling = t->m_firstChild;
t->m_firstChild = newChild;
m_size++;
break;
}
}
}
size_t BkTree::EditDistance( const std::string &left, const std::string &right ) {
size_t asize = left.size();
size_t bsize = right.size();
std::vector<size_t> prevrow(bsize+1);
std::vector<size_t> thisrow(bsize+1);
for(size_t i = 0; i <= bsize; i++)
prevrow[i] = i;
for(size_t i = 1; i <= asize; i ++) {
thisrow[0] = i;
for(size_t j = 1; j <= bsize; j++) {
thisrow[j] = std::min(prevrow[j-1] + size_t(left[i-1] != right[j-1]),
1 + std::min(prevrow[j],thisrow[j-1]) );
}
std::swap(thisrow,prevrow);
}
return prevrow[bsize];
}
void BkTree::get_friends(std::string center, std::deque<std::string>& flv) {
if( !m_root ) return ;
std::queue< Node* > q;
q.push( m_root );
while( !q.empty() ) {
Node *t = q.front();
q.pop();
if ( !t ) continue;
size_t d = EditDistance( t->m_item, center );
if( d == 1 ) {
if ( t->visited == false ) {
flv.push_back(t->m_item);
t->visited = true;
}
}
Node *ch = t->m_firstChild;
q.push(ch);
while( ch ) {
if( ch->m_distToParent >= 1 )
q.push(ch);
ch = ch->m_nextSibling;
}
}
return;
}
int main( int argc, char **argv ) {
BkTree *pDictionary = new BkTree();
std::ifstream dictFile("word.list");
std::string line;
if (dictFile.is_open()) {
while (! dictFile.eof() ) {
std::getline (dictFile,line);
if ( line.size()) {
pDictionary->insert(line);
}
}
dictFile.close();
}
std::deque<std::string> flq;
pDictionary->get_friends("aa", flq);
int counter = 0;
while ( !flq.empty()) {
counter++;
std::string nf = flq.front();
flq.pop_front();
pDictionary->get_friends(nf, flq);
}
std::cout << counter << std::endl;
return 0;
}
任何关于提高速度或任何其他合适数据结构的评论。
假设以下是我的字典。
aa
aah
aal
aam
aami
aamii
aaaaaaaaaaaaaaaaaaaaaaaaa
我试图找到aa
答案social network
是5
.
aa -> aah aal aam
aah -> aa, aal aam
aal -> aa, aah, aam
aam -> aa, aah, aal, aami
aami -> aam, aamii
ANSWER : -> aah + aal + aam + aami + aamii
使用 Trie 阅读快速简便的列文施泰因距离,详细了解解决此问题的有效方法。
在您的示例代码中,"朋友的朋友"的编辑距离不是 2(或 0(吗? 您可能可以停止使用深度优先搜索,而直接比较 Levenshtein 距离是 0 还是 2(零表示编辑被第二个关系"撤消",例如 A -> B 的编辑距离为 1,B -> C 的编辑距离为 1,这完全撤消了 A -> B 编辑,A -> C 之间的编辑距离为零(。
这似乎也与梯子谜题这个词有关。 此处提供了变化爆炸式的绝佳可视化。 我想对于您的算法,您想找到长度为 2 的单词对之间的所有路径吗? 也许将其表达为所有对的阶梯问题会给你一种新的方法?
相关文章:
- 一位朋友将模板函数缩写为clang和gcc
- C++中的MSD基排序(字典序)
- 班级的朋友是不可接近的
- 与朋友声明相反
- C++中是否有任何函数等同于python中字典的get函数?
- 为什么即使我声明了朋友类,我也会收到错误"无法访问类中声明的私人成员"
- 类似虚拟的朋友功能?
- 替代在python中制作邻接列表与图形问题的字典?(如 C++ 中的 vector<vector<int&g
- 为什么C++需要公共继承,忽略朋友声明,才能使动态向下工作?
- 在朋友类中使用模板
- 访问私人成员而不使用朋友类
- 类和朋友在它们之间起作用
- "朋友"成员函数和 GCC 与 Clang
- C++中类似Python字典的结构?
- 朋友声明的复杂范围界定规则有什么意义?
- C++:让函数成为多个类的朋友?
- 有没有办法C++将给定类的功能限制为仅另一个类(不使用继承,朋友)?
- 朋友,前瞻宣言,C++
- C++ 按数值对元组<字符串、浮点数>然后按字典顺序排序的向量
- 使用列文施泰因距离在字典中查找朋友的朋友