【问题标题】:Add items to a vector recursively递归地将项目添加到向量
【发布时间】:2011-05-16 02:28:19
【问题描述】:

我正在尝试创建一个递归函数,该函数输出一个字符串向量,其中包含给定字符串的所有可能的单词组合(同时保留字母顺序)。基本上,这是一个自动更正打字程序的基础,它产生的效果类似于 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”的向量,“去”,“ho”,“uo”,“yl”,“tl”,“gl”,“hl”,“ul”}。如果 str 为“y”,则输出应该是包含值 {“y”、“t”、“g”、“h”、“u”} 的向量。

存储在相邻键中的 26 个向量包含与存储在向量第一个位置的字母相邻的字母。

a   qwsz
b   vghjn
c   xdfgv
d   zserfcx
//and so on

我被这个函数卡住了,不知道如何递归地构建这个向量。

【问题讨论】:

  • 我不明白这个问题。你能举出更多的例子吗?我不明白为什么“y”应该映射到{“y”、“t”、“g”、“h”、“u”}。编辑:我刚刚意识到“相邻”是指在 QWERTY 键盘上彼此相邻的字母?输出字符串的长度与输入字符串 (str) 的长度相同,但是每个字母在键盘上被替换为附近的字母?
  • 正确 -- 每个字母都替换为键盘上它附近的字母,以及作为 (str) 一部分的原始字母。
  • 快速观察:您是否考虑过返回的向量会很快变大。最坏的情况是 8^N 个条目,其中 N 是输入字符串中的字母数,每个字母的长度为 N 个字符;到 7 个字母时,您正在查看大约 14MB!
  • 我已经想到了这一点,但这是一个非常初级的解决方案,将慢慢建立。这个递归函数只是一个基础。

标签: c++ recursion vector


【解决方案1】:

(更新:格林威治标准时间 2130 周日:我的答案已经大为改观。我认为现在可行。)

这是一个完整的程序。我认为我会做出其他更改,但我正在努力保持您最初解决方案的精神。 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;
        }
}

返回

【讨论】:

  • 这个方法产生向量 {"yp", "p"},而不是 {"yp", "tp", "gp", "hp", "up", "yo", “to”、“go”、“ho”、“uo”、“yl”、“tl”、“gl”、“hl”、“ul”}。映射到“y”的字母是{“t”、“g”、“h”、“u”},映射到“p”的字母是{“o”、“l”}。
  • 我刚刚上传了一个不同的答案。我现在正确地测试了这个,我应该第一次这样做!
【解决方案2】:

也许是这样的?我没有测试它,因为我没有你的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);
            }
        }
    }
}

【讨论】:

  • 您可以只传入一个输出迭代器,而不是将results 作为输出参数传递。这更加灵活。
猜你喜欢
  • 2016-08-12
  • 2022-01-16
  • 1970-01-01
  • 2020-01-30
  • 2010-10-14
  • 2016-06-09
  • 1970-01-01
  • 1970-01-01
  • 2019-03-12
相关资源
最近更新 更多