我正在尝试创建一个递归函数,该函数输出一个字符串向量,该字符串包含给定字符串的所有可能的单词组合(同时保留字母顺序)。基本上,自动校正打字程序的基础,产生类似于iPhone的效果。
vector<string> allPossibleWords(string str, vector<vector<char> > & adjacentKeys)
{
vector<string> words;
cout << str << endl;
if (str.length() == 0)
{
return words;
}
char firstLetter = str[0];
string restOf = str.substr(1, str.length() - 1);
int position = position_in_vector(firstLetter);
for (int i = 0; i < adjacentKeys[position].size(); i++)
{
string temp(1, adjacentKeys[position][i]);
words.push_back(temp);
}
//allPossibleWords(restOf, adjacentKeys);
}
int position_in_vector(char letter)
{
return (letter % 97);
}
例如,如果str是“yp”,则输出应该是包含值{“yp”,“tp”,“gp”,“hp”,“up”,“yo”,“to”的向量,“go”,“ho”,“uo”,“yl”,“tl”,“gl”,“hl”,“ul”}。如果str为“y”,则输出应为包含值{“y”,“t”,“g”,“h”,“u”}的向量。
存储在adjacentKeys中的26个向量包含与存储在向量的第一个位置的字母相邻的字母。
a qwsz
b vghjn
c xdfgv
d zserfcx
//and so on
我坚持使用这个函数,并且无法弄清楚如何递归地构建这个向量。
答案 0 :(得分:1)
(更新时间:格林尼治标准时间周日21:30:我已经明显改变了我的答案。我认为现在这样做了。)
这是一个完整的程序。我认为还会有其他变化,但我正在努力保持初始解决方案的精神。在str.length()==0
时返回单个空单词非常重要。
#include <vector>
#include <iostream>
using namespace std;
vector<string> allPossibleWords(string str, vector<vector<char> > & adjacentKeys)
{
vector<string> words;
// cout << "str=" << str << endl;
if (str.length() == 0)
{
words.push_back("");
return words;
}
char firstLetter = str[0];
// cout << "firstLetter=" << firstLetter << endl;
int positionInAdjacentKeys = 0;
while(positionInAdjacentKeys < adjacentKeys.size() && adjacentKeys.at(positionInAdjacentKeys).front() != firstLetter) {
++ positionInAdjacentKeys;
}
vector<char> & adjacent = adjacentKeys.at(positionInAdjacentKeys);
string restOf = str.substr(1, str.length() - 1);
// cout << firstLetter << ":" << restOf << endl;
// int position = position_in_vector(firstLetter);
vector<string> recursiveWords = allPossibleWords(restOf, adjacentKeys);
for (int i = 0; i < adjacent.size(); i++)
{
const string temp(1, adjacent[i]);
// cout << " temp=" << temp << endl;
for(vector<string>::const_iterator i = recursiveWords.begin(); i != recursiveWords.end(); i++)
{
// cout << "new word=" << temp + *i << endl;
words.push_back(temp + *i);
}
}
return words;
}
int main() {
vector<vector<char> > adj;
vector<char> v1;
v1.clear();
v1.push_back('p');
v1.push_back('o');
v1.push_back('l');
adj.push_back(v1);
v1.clear();
v1.push_back('y');
v1.push_back('t');
v1.push_back('g');
v1.push_back('h');
v1.push_back('u');
adj.push_back(v1);
adj.push_back(v1);
vector<string> words = allPossibleWords("yp", adj);
for(vector<string> :: const_iterator i = words.begin(); i != words.end(); i++) {
cout << *i << endl;
}
}
返回
答案 1 :(得分:0)
也许是这样的?我没有测试过,因为我没有你的adjacentKeys
矩阵。它可能会稍微优化一下,但我不认为这种方法可以很好地扩展。
我建议从不同的角度攻击问题,可能将你的字典存储在某种K-ary tree中,并且有几个指针在树上行走,根据你的邻接矩阵跟随分支。这将停止生成无效的单词(以及随后的查找以检查有效性),因为分支只存在于有效单词存在的位置。
using namespace std;
void allPossibleWordsHelper(const string& str,
string::size_type index,
const vector<vector<char> >& adjacentKeys,
vector<string>& results)
{
if (str.length() == 0)
{
return;
}
std::string head = (index > 0) ? str.substr(0, index) : "";
std::string tail = (index < str.length() - 1) ? str.substr(index + 1) : "";
vector<string> possibleHeads;
string::size_type headIndex = (str.length() - index) / 2;
allPossibleWordsHelper(head, headIndex, adjacentKeys, possibleHeads);
vector<string> possibleTails;
allPossibleWordsHelper(tail, index + headIndex, adjacentKeys, possibleTails);
int pos = str[index] - 'a';
vector<string>::const_iterator headi;
vector<string>::const_iterator headi_end = possibleHeads.end();
vector<string>::const_iterator taili;
vector<string>::const_iterator taili_end = possibleTails.end();
vector<char>::const_iterator aki;
vector<char>::const_iterator aki_end = adjacentKeys[pos].end();
for(headi = possibleHeads.begin(); headi != headi_end; ++headi)
{
for (aki = adjacentKeys[pos].begin(); aki != aki_end; ++aki)
{
for (taili = possibleTails.begin(); taili != taili_end; ++taili)
{
string suggestedWord = *headi + *aki + *taili;
results.push_back(suggestedWord);
}
}
}
}