动态规划 - 分词
Posted
技术标签:
【中文标题】动态规划 - 分词【英文标题】:Dynamic Programming - Word Break 【发布时间】:2014-08-06 18:55:20 【问题描述】:我正在尝试解决this问题。问题如下 给定一个输入字符串和一个单词字典,找出输入字符串是否可以分割成一个空格分隔的字典单词序列。
字典是一个字符串数组。
我的方法是以下递归 fn,存储递归调用的结果。输出很好,但我看到存储的结果从未使用过。 我的解决方案希望是正确的,因为它通过了测试用例。但是如果我知道是否使用了 DP,那就太好了。
代码是:
#include <iostream>
#include <string.h>
using namespace std;
int r[100][100] = 0; //To Store the calculated values
bool searchWord(char q[], char D[][20], int start, int end)
cout << "In Search Word Loop with " << start << " " << end << endl;
char temp[end - start + 1];
int j = 0;
for (int i = start; i <= end ; ++i)
//cout << "Looping i " << i << endl;
temp[j] = q[i];
j++;
// cout << "For Word " << temp << endl;
for (int i = 0; i < 12; ++i)
// cout << "Comparing with " << D[i] << endl;
if (!strcmp(temp, D[i]))
cout << "Found Word" << temp << " " << D[i] << endl;
return 1;
return 0;
bool searchSentence(char q[], char D[][20], int qstart, int qend)
cout << "In Search Sentence Loop" << endl;
if (r[qstart][qend] != 0)
cout << "DP Helped!!!" << endl;
return 1;
if (qstart == qend)
if (searchWord(q, D, qstart, qstart))
return 1;
else return 0;
if (qstart > qend) return 1;
int i;
for (i = qstart; i <= qend; i++)
if (searchWord(q, D, qstart, i))
r[i + 1][qend] = searchSentence(q, D, i + 1, qend);
if (r[i + 1][qend] == 1) return 1;
return 0;
int main()
char D[20][20] = "i", "like", "sam", "sung", "samsung", "mobile", "ice", "cream", "icecream", "man", "go", "mango";
char q[100] = "samsungmango";
int index = 0; char ch;
ch = q[0];
while (ch != '\0')
index++;
ch = q[index];
if (searchSentence(q, D, 0, index - 1))
cout << "Yes" << endl;
else cout << "No" << endl;
【问题讨论】:
【参考方案1】:递归是强制性的吗?我明白了,迭代 DP 解决方案最简单且紧凑:
#include <stdio.h>
#include <string.h>
int main()
const char *D[] = "i", "like", "sam", "sung", "samsung", "mobile", "ice", "cream", "icecream", "man", "go", "mango", NULL;
const char q[] = "samsungmango";
char dp[100];
short d_len[20];
memset(dp, 0, sizeof(dp));
dp[0] = 1; // 0 element is always reacheable
int i, j;
// compute dict string lengths
for(i = 0; D[i]; i++)
d_len[i] = strlen(D[i]);
// Compute splits using DP array
for(i = 0; q[i] != 0; i++)
if(dp[i]) // this index is reacheable
for(j = 0; D[j]; j++) // try to make next reacheable indexes
if(strncmp(&q[i], D[j], d_len[j]) == 0)
dp[i + d_len[j]] = 1; // That position is reacheable, too
// if EOLN(q) is reached, then yes
printf("Answer is %s\n", dp[i]? "YES" : "NO");
// main
【讨论】:
这个问题的最佳方法。简单有效。 你所说的“可达”是什么意思? reachable = 这个位置可以通过字典单词的组合到达。位置 0 代表“空字符串”。【参考方案2】:您的代码实际上是错误的。要使您的代码失败,请尝试像“likeman”这样的输入
请注意,函数searchSentence
可能有两个不同的返回值,即 0 或 1。因此,如果您将 r
数组初始化为 0,则无法保证在 r[x][y] = 0
时它是一个新状态。用一些不可能的值初始化 r 数组,如该程序的 -1 或 2 并再次测试。现在你可以很容易地确认如果r[qbegin][qend] != -1
那么这个状态已经被检查了所以你可以从这里返回r[qbegin][qend]
更新代码:
#include <iostream>
#include <string.h>
using namespace std;
int r[100][100]; //To Store the calculated values
bool searchWord(char q[], char D[][20], int start, int end)
cout << "In Search Word Loop with " << start << " " << end << endl;
char temp[end - start + 1];
int j = 0;
for (int i = start; i <= end ; ++i)
//cout << "Looping i " << i << endl;
temp[j] = q[i];
j++;
temp[j] = '\0';
//cout << "For Word " << temp << endl;
for (int i = 0; i < 12; ++i)
// cout << "Comparing with " << D[i] << endl;
if (!strcmp(temp, D[i]))
cout << "Found Word" << temp << " " << D[i] << endl;
return 1;
return 0;
bool searchSentence(char q[], char D[][20], int qstart, int qend)
cout << "In Search Sentence Loop" << endl;
if (r[qstart][qend] != -1)
cout << "DP Helped!!!" << endl;
return r[qstart][qend];
if (qstart == qend)
if (searchWord(q, D, qstart, qstart))
return 1;
else return 0;
if (qstart > qend) return 1;
int i;
for (i = qstart; i <= qend; i++)
if (searchWord(q, D, qstart, i))
r[i + 1][qend] = searchSentence(q, D, i + 1, qend);
if (r[i + 1][qend] == 1) return 1;
return 0;
int main()
char D[20][20] = "i", "like", "sam", "sung", "samsung", "mobile", "ice", "cream", "icecream", "man", "go", "mango";
char q[100] = "ilike";
int index = 0; char ch;
ch = q[0];
memset(r, -1, sizeof(r));
while (ch != '\0')
index++;
ch = q[index];
if (searchSentence(q, D, 0, index - 1))
cout << "Yes" << endl;
else cout << "No" << endl;
P.S : 有一些多余的代码行,但我没有更改它们,我在函数 searchWord
中的字符数组 temp 的末尾添加了一个空字符
【讨论】:
这不是逻辑,基本上这是一个错误和初始化的东西以上是关于动态规划 - 分词的主要内容,如果未能解决你的问题,请参考以下文章
算法动态规划 ④ ( 动态规划分类 | 坐标型动态规划 | 前缀划分型动态规划 | 前缀匹配型动态规划 | 区间型动态规划 | 背包型动态规划 )
算法动态规划 ④ ( 动态规划分类 | 坐标型动态规划 | 前缀划分型动态规划 | 前缀匹配型动态规划 | 区间型动态规划 | 背包型动态规划 )
算法动态规划 ② ( 动态规划四要素 | 动态规划状态 State | 动态规划初始化 Initialize | 动态规划方程 Function | 动态规划答案 Answer )