因此,我一直在尝试解决分词动态编程问题,这基本上意味着给定一个字符串字典和一个字符串,看看字典中的单词是否可以组合成字符串。例如,给定单词“ applepenapple”和字典[“ apple”,“ pen”],它应该返回true。
我有一个有效的Java解决方案,但我正在尝试提高C ++技能。我的问题是,即使我的代码看上去与Java中的工作解决方案极为相似,我也没有通过适当的测试案例,而且我不知道为什么。
C ++代码:
bool wordBreak(string s, vector<string> &wordDict) {
vector<int> bArr(s.length(), -1);
unordered_set<string> set(wordDict.begin(), wordDict.end());
return wordBreak(s, bArr, 0, set);
}
bool wordBreak(string s, vector<int> &bArr, int start, unordered_set<string> &set) {
if (start == s.length())
return true;
//If we have a memoized solution to this problem, avoid recurion
if (bArr[start] != -1)
return (bArr[start] == 1);
for (int end = start + 1; end <= s.length(); end++) {
if (set.count(s.substr(start, end)) && wordBreak(s, bArr, end, set)) {
bArr[start] = 1;
return bArr[start] == 1;
}
}
bArr[start] = 0;
return false;
}
使用Java的工作代码:
public boolean wordBreak(String s, List<String> wordDict) {
Integer[] memo =new Integer[s.length()];
Arrays.fill(memo,-1);
return word_Break(s, new HashSet(wordDict), 0, memo);
}
public boolean word_Break(String s, Set<String> wordDict, int start, Integer[] memo) {
if (start == s.length()) {
return true;
}
if (memo[start] != -1) {
return memo[start]==1;
}
for (int end = start + 1; end <= s.length(); end++) {
if (wordDict.contains(s.substring(start, end)) && word_Break(s, wordDict, end, memo)) {
memo[start] = 1;
return memo[start] == 1;
}
}
memo[start] = 0;
return false;
}
对于带有字典[“ apple”,“ pen”]的“ applepenapple”,C ++代码返回false,但我不知道为什么,因为java返回true才是正确的。两种解决方案之间的唯一主要区别(我认为)是我的C ++使用向量而不是Java代码中的本机数组。最初,我认为这可能与使用自动存储(堆栈)与自由存储(堆)的C ++有关,这就是为什么我使用向量而不是C样式的数组来避免由于RAII而导致的内存管理的原因。尽管进行了此更改,该错误仍然存在。有一个更简单的解决方案可以完全避免递归,但是我很好奇为什么C ++返回的输出与Java不同。
答案 0 :(得分:4)
我看到一个潜在的问题。来自java.lang.String
Javadoc(重点是我):
public String substring(int beginIndex, int endIndex)
返回一个新字符串,该字符串是该字符串的子字符串。子字符串从指定的beginIndex开始,并扩展到索引endIndex-1处的字符。因此,子字符串的长度为endIndex-beginIndex。
示例:
"hamburger".substring(4, 8) returns "urge" "smiles".substring(1, 5) returns "mile"
参数:
beginIndex-起始索引(包含首尾)。
endIndex-结束索引,排他。
来自cppreference.com documentation on strings:
basic_string substr( size_type pos = 0, size_type count = npos ) const;
返回一个子字符串[pos,pos + count)。如果所请求的子字符串超出了字符串的末尾,或者如果count == npos,则返回的子字符串为[pos,size())。
参数
pos-要包含的第一个字符的位置
count-子字符串的长度
也就是说,在Java中,应将索引作为第二个参数传递给String.substring(...)
,但在C ++中,应将长度传递给basic_string::substr(...)
。但是,您正在这样做:
s.substr(start, end)
和
s.substring(start, end)
在两种情况下
也许将C ++调用调整为
s.substr(start, end - start)
会起作用吗?