我怎样才能找到部分单词匹配/找到c ++
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我怎样才能找到部分单词匹配/找到c ++相关的知识,希望对你有一定的参考价值。
我正在制作一个类似拼字游戏的游戏。我的目标是有5个随机字母,这些字母可能与我制作的字典中的至少一个单词匹配,因此游戏可以开始。我已经完成了这个,但由于5个字母是随机的,因此它很可能会匹配字典中的一个单词。我已经完成了测试运行并获得了随机字母,但每次都没有匹配(但它的工作硬编码)。我想如果我能找到一个部分匹配,我可以保留构成单词一部分的字母,并为那些没有单词的字母保留不同的字母。问题是,我不知道该怎么做。
这是我的五个随机字母的代码:
void fiveLetters()
{
srand(time(NULL));
for (int i =0; i<=4; i++) // display 5 random letters
{
int n = rand()%26;
char letter = (char)(n+97);
letters[i] = letter;
cout << letters[i]<< " ";
}
letters[5] = ' '; // last value in char array null value so I can convert to string
attempt = letters; // the 4 letters
checkWords();
}
检查它是否与我使用的单词匹配:
void checkWords()
{
if (find(words.begin(),words.end(), attempt) != words.end()) // if matches word in set
{
cout << " Words found" << endl;
}
else // if it doesn't match
{
cout << "cannot find word " << endl;
attempt.clear();
fiveLetters();
}
}
字典是一个包含大量单词的文本文件,但是因为我只是在实现它之前试图让事情起作用,所以我使用5-10个单词并将它们放在set<string>
中。对不起,长时间阅读,任何帮助表示赞赏!
此示例演示如何使用Trie递归搜索加载到其中的单词,使用搜索条件,如可用字母数,最小字长和最大数量的“缺失”字母 - 使用的字母不包含在“可用”中“ 信件。
这个Trie是一个26-ary树,所以每个节点有26个子节点,每个字母对应一个字母。使用单词中的第一个字母选择根节点的子节点,第二个字母选择此子节点中的一个,依此类推。节点包含一个布尔值,表示单词以该节点结束。然而,这样的节点不是“叶子”,因为终止的单词可能是较长单词的前缀(节点终止“球”,但仍具有“气球”的子分支)。
Trie以及递归搜索对于您的特定任务来说非常快速。 (顺便说一句,递归搜索不使用递归函数,它将每个级别的上下文存储在基于矢量的堆栈上)。
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <fstream>
#include <random>
#include <algorithm>
class Trie {
// branch_count defines the number of characters which are combined to make words
// 26 is the number of letters, interpreted case-insensitively
static const int branch_count = 26;
// index_map takes a character and returns a number between 0 and branch_count-1
static int index_map(char c) {
if((c >= 'a') & (c <= 'z')) return c - 'a';
if((c >= 'A') & (c <= 'Z')) return c - 'A';
return -1;
}
// index_unmap takes an index, between 0 and branch_count-1, and returns
// the canonical character representation for that index
static char index_unmap(int index) {
return char('a' + index);
}
// verify_word returns true if all characters in the string map to an index
// returns false if at least one character is not recognized
static bool verify_word(const std::string& word) {
for(auto&& c : word) {
if(index_map(c) == -1) return false;
}
return true;
}
// Node is the Trie's branch_count-ary tree node class
struct Node {
Node* child_nodes[branch_count];
bool terminates_word;
Node() : terminates_word(false) {
for(auto& p : child_nodes) { p = nullptr; }
}
};
// make_lower(str) changes upper-case letters in str to lower-case (in-place)
static void make_lower(std::string& str) {
for(auto& c : str) {
if((c >= 'A') & (c <= 'Z')) {
c += 'a' - 'A';
} } }
// is_space_char(x) returns true when c is some kind of
// unprintable or blank, but nonzero, character
static bool is_space_char(char c) { return (c > 0) & (c <= ' '); }
// trim(str) removes whitespace from the left and right sides
// of str (str is modified in-place)
static void trim(std::string& str) {
const auto len = str.length();
if(!len) return;
auto i = len-1;
if(is_space_char(str[i])) {
for(--i; i+1; --i) {
if(!is_space_char(str[i])) {
str.resize(i+1);
break;
} } }
if(!(i+1)) {
str.clear();
return;
}
i=0;
if(is_space_char(str[i])) {
for(++i;; ++i) {
if(!is_space_char(str[i])) {
str = str.substr(i);
return;
} } } }
Node *root;
int node_count;
int word_count;
public:
// Trie::AddWord(word) stores a string in the Trie
void AddWord(std::string word) {
if(word.empty()) return;
make_lower(word);
if(!verify_word(word)) return;
Node *p = root;
for(const auto c : word) {
const int child_index = index_map(c);
if(child_index == -1) {
// verify_word(word) should have caught this.
// Well-behaved, but might use excess memory.
return;
}
Node *pchild = p->child_nodes[child_index];
if(!pchild) {
p->child_nodes[child_index] = pchild = new Node;
++node_count;
}
p = pchild;
}
if(!p->terminates_word) {
p->terminates_word = true;
++word_count;
} }
// LoadWords(input_stream) loads all line-delimited words from
// the stream into the Trie
int LoadWords(std::istream& stream_in) {
const int start_count = word_count;
std::string line;
while(std::getline(stream_in, line)) {
trim(line);
AddWord(line);
}
return word_count - start_count;
}
// LoadWords(filename) loads all line-delimited words from
// the file at the given path
int LoadWords(const std::string& file_path) {
std::ifstream stream_in(file_path.c_str());
return LoadWords(stream_in);
}
// WordCount() returns the number of words loaded so far
int WordCount() const { return word_count; }
// select_type is a helper for specifying iterator behavior
template <bool select_A, typename A, typename B>
struct select_type { typedef A type; };
template <typename A, typename B>
struct select_type<false, A, B> { typedef B type; };
template <bool select_A, typename A, typename B>
using select_type_t = typename select_type<select_A, A, B>::type;
// The iterator class is used for begin() and end(), as a minimal
// implementation compatible with range-based for,
// as well as by the destructor when destroying the
// tree's Node objects.
template <bool is_const=true, bool delete_iter=false>
class iterator {
friend class Trie;
typedef select_type_t<is_const, const Node*, Node*> pnode_t;
struct context {
pnode_t node;
int child_index;
};
std::vector<context> stack;
pnode_t advance() {
for(;;) {
if(stack.empty()) return nullptr;
pnode_t p = stack.back().node;
int &child_index = stack.back().child_index;
while(++child_index < branch_count) {
pnode_t pchild = p->child_nodes[child_index];
if(pchild) {
stack.push_back({pchild, -1});
if(!delete_iter && pchild->terminates_word) return nullptr;
break;
} }
if(stack.back().child_index == branch_count) {
stack.pop_back();
if(delete_iter) return p;
} } }
public:
iterator(pnode_t root) {
stack.push_back({root, -1});
if(!delete_iter) advance();
}
iterator() {}
std::string operator * () const {
if(stack.empty()) return std::string();
std::string word;
for(int i=0; stack[i].child_index != -1; ++i) {
word += index_unmap(stack[i].child_index);
}
return word;
}
iterator& operator ++ () {
advance();
return *this;
}
bool operator != (const iterator& iter) const {
if(stack.size() != iter.stack.size()) return true;
const int size = static_cast<int>(stack.size());
for(int i=0; i<size; ++i) {
if(stack[i].node != iter.stack[i].node) return true;
}
return false;
}
};
// ctor
Trie() : root(new Node), node_count(1), word_count(0) {}
// dtor
~Trie() {
iterator<false, true> iter(root);
int count = 0;
while(auto pn = iter.advance()) {
delete pn;
++count;
}
//std::cout << "Final word count: " << word_count << '
';
//std::cout << count << " of " << node_count << " Node objects deleted
";
}
// const_iterator defined from iterator with template parameter
// for selecting const Node pointers
typedef iterator<true> const_iterator;
const_iterator begin() const { return const_iterator(root); }
const_iterator end() const { return const_iterator(); }
// FindWords:
以上是关于我怎样才能找到部分单词匹配/找到c ++的主要内容,如果未能解决你的问题,请参考以下文章
从输入字段中查找部分单词匹配,我还发现来自 HTML 代码的结果。为啥?