【问题标题】:Split string into words将字符串拆分为单词
【发布时间】:2011-06-12 21:55:09
【问题描述】:

我正在寻找最有效的算法来从字符串中形成所有可能的单词组合。例如:

Input String: forevercarrot

Output:

forever carrot
forever car rot
for ever carrot
for ever car rot

(所有单词都应该来自字典)。

我可以想到一种蛮力方法。 (找到所有可能的子字符串并匹配)但是有什么更好的方法?

【问题讨论】:

  • 您的蛮力方法是正确的。想象一下,除了请求外语单词之外,您遇到了同样的问题。

标签: algorithm string dictionary word substring


【解决方案1】:

输入字符串:forevercarrot

输出:

永远的胡萝卜 永远的汽车腐烂 永远的胡萝卜 永远的汽车腐烂

程序:

#include<iostream>
#include<string>
#include<vector>
#include<string.h>
void strsplit(std::string str)
{
   int len=0,i,x,y,j,k;
   len = str.size();
   std::string s1,s2,s3,s4,s5,s6,s7;
   char *c = new char[len+1]();
   char *b = new char[len+1]();
   char *d = new char[len+1]();
   for(i =0 ;i< len-1;i++)
   {
       std::cout<<"\n";
       for(j=0;j<=i;j++)
       {
          c[j] = str[j];
          b[j] = str[j];
          s3 += c[j];
          y = j+1;
       }
       for( int h=i+1;h<len;h++){
          s5 += str[h];
       }
       s6 = s3+" "+s5;
       std::cout<<" "<<s6<<"\n";
       s5 = "";
       for(k = y;k<len-1;k++)
       {
          d[k] = str[k];
          s1 += d[k];
          s1 +=  " ";
          for(int l = k+1;l<len;l++){
           b[l] = str[l];
           s2 += b[l];
         }
       s4 = s3+" "+s1+s2;
       s7 = s4;
       std::cout<<" "<<s4<<"\n";
       s3 = "";s4 = "";
       }
       s1 = "";s3 = "";
    }
}

int main(int argc, char* argv[])
{
    std::string str;
    if(argc < 2)
                std::cout<<"Usage: "<<argv[0]<<" <InputString> "<<"\n";
    else{
                str = argv[1];
                strsplit(str);
    }

return 0;
}

【讨论】:

    【解决方案2】:

    查看这个问题,它有更好的答案。这是一个标准的动态规划问题:

    How to split a string into words. Ex: "stringintowords" -> "String Into Words"?

    【讨论】:

      【解决方案3】:

      使用prefix tree 作为您的已知单词列表。可能像myspell 这样的库已经这样做了。尝试使用现成的。

      一旦找到匹配项(例如“car”),拆分计算:一个分支开始寻找新词(“rot”),另一个分支继续探索当前开头的变体(“carrot”)。

      每次拆分计算时,您实际上都会在字符串中维护一对(start_position, current_position) 的偏移量队列。多个线程可以并行地从该队列中弹出并尝试继续从start_position 开始并且已知直到current_position 的单词,但不会在那里结束。当找到一个单词时,它会被报告并从队列中弹出另一对。当不可能时,不会产生任何结果。当分裂发生时,一个新的对被添加到队列的末尾。最初队列包含(0,0)

      【讨论】:

      • 另外确保你不要重复计算'carrot'的分割两次——一次是'forever',一次是'forever'。缓存部分结果:为每个 [i..n] 设置(可能的拆分)。
      【解决方案4】:

      一个伪代码实现,利用字符串的每个部分都必须是一个单词的事实,我们不能跳过任何东西。我们从字符串的开头开始工作,直到第一位是一个单词,然后生成字符串其余部分的所有可能组合。完成此操作后,我们将继续前进,直到找到第一个单词的任何其他可能性,依此类推。

      allPossibleWords(string s, int startPosition) {
          list ret
          for i in startPosition..s'length
              if isWord(s[startPosition, i])
                  ret += s[startPostion, i] * allPossibleWords(s, i)
          return ret    
      }
      

      此代码中的问题是您最终会重复计算 - 在您的示例中,您最终将不得不计算 allPossibleWords("carrot") 两次 - 一次在 ["forever", allPossibleWords["carrot"]] 中,一次在 ["for", "ever", allPossibleWords["carrot"]] 中。所以记住这一点是需要考虑的。

      【讨论】:

        猜你喜欢
        • 2014-06-09
        • 1970-01-01
        • 2022-01-18
        • 2011-10-23
        • 2011-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多