Lintcode--009(单词切分)
http://www.lintcode.com/zh-cn/problem/word-break/
单词切分
给出一个字符串s和一个词典,判断字符串s是否可以被空格切分成一个或多个出现在字典中的单词。
样例
给出
s = "lintcode"
dict = ["lint","code"]
返回 true 因为"lintcode"可以被空格切分成"lint code"
标签:动态规划
解题:
题目理解:字典中的词是一个set,只要所给字符串可以被字典中给的词拼接出来,则表示可以切分。字典中的词语可以被重复使用;
例如:
Example 1:
Input: s = "leetcode", wordDict = ["leet", "code"] Output: true Explanation: Return true because "leetcode" can be segmented as "leet code".
Example 2:
Input: s = "applepenapple", wordDict = ["apple", "pen"] Output: true Explanation: Return true because "applepenapple" can be segmented as "apple pen apple". Note that you are allowed to reuse a dictionary word.
Example 3:
Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] Output: false
还是动态规划问题, 动态规划的本质:根据已知结论推理未知结论。
思路: s = lintcode 可以分为 l和intcode,若是l是可分割单词,并且intcode单词在dict中,则表示s也是可分割单词。
若不符合,s = lintcode 可以分为 li和ntcode,若是li是可分割单词,并且ntcode单词在dict中,则表示s也是可分割单词。
...
同理得出BWord[ n ]表示字符串S[0,n]是否是可分割单词,是则为true,否为false。
BWord[ n ] = BWord[ i ] &&( S[ i+1 ,n ]在dict中 )
C++代码:
class Solution { public: /** * @param s: A string s * @param dict: A dictionary of words dict */ bool wordBreak(string s, unordered_set<string> &dict) { // write your code here //还是动态规划问题,先理解清楚题意; //将问题转化为小规模的问题,先看子问题是不是,然后在扩展; //程序思路很清楚; int slen=s.size(); int dlen=dict.size(); if(slen==0&&dlen==0){ return true; } if(slen==0||dlen==0){ return false; } bool* dp=new bool[slen+1]; dp[0]=true; for(int i=0;i<slen;i++){ if(!dp[i]){ continue;//若dp[i]为false,则执行下一个i; } unordered_set<string>::iterator it; for(it=dict.begin();it!=dict.end();++it){ string value=*it; int lv=value.size();//求出字典中字符串的长度; if(i+lv>slen){ continue;//如果长度大于s,则执行字典中的下一个字符串; } string last=s.substr(i,lv); //以i为初始地址,偏移量为lv if(last==value){ dp[i+lv]=true; } } } return dp[slen]; } };
官方标准解法:
class Solution {
public:
/**
* @param s: A string
* @param wordSet: A dictionary of words dict
* @return: A boolean
*/
bool wordBreak(string &s, unordered_set<string> &wordSet) {
// write your code here
int len=s.size();
vector<bool> flag(len+1,false);
flag[0] = true;
for(int i=1;i<len+1;i++){
for(int j=i-1;j>=0;j--){
if(flag[j]&&wordSet.count(s.substr(j,i-j))!=0){
flag[i]=true;
break;
}
}
}
return flag[len];
}
};
注意,在使用递归方法解题时,如果需要存储中间结果,要定义一个全局变量实现,否则会有问题;
注:str.substr(startpos, length);
其中 startpos 是起始字符的序号,length 是[从 startpos 开始]取的字符串长度(包括startpos )
# include<iostream>
# include<vector>
# include<string>
#include <algorithm>
# include<unordered_set>
using namespace std;
bool wordBreak(string &s, unordered_set<string> &wordSet) {
// write your code here
int len=s.size();
vector<bool> flag(len+1,false);
flag[0] = true;
for(int i=1;i<len+1;i++){
for(int j=i-1;j>=0;j--){
if(flag[j]&&wordSet.count(s.substr(j,i-j))!=0){
flag[i]=true;
break;
}
}
}
return flag[len];
}
bool match(vector<string>& word_dict, string& str){
int len = str.size();
vector<bool> dp(len+1,false);
dp[0]=true;
for(int i=1;i<len+1;i++){
for(int j=i-1;j>=0;j--){
if(dp[j]&&(find(word_dict.begin(),word_dict.end(),str.substr(j,i-j))!=word_dict.end())){
dp[i]=true;
break;
}
}
}
return dp[len];
}
int main(){
vector<string> word_dict = {"didi","xing","chu"};
unordered_set<string> word = {"didi","chu","xing"};
string target = "didichuxing";
// bool res = wordBreak(target,word);
bool res=match(word_dict,target);
cout<<res<<endl;
return 0;
}
单词拆分III
样例
样例1
输入:
"CatMat"
["Cat", "Mat", "Ca", "tM", "at", "C", "Dog", "og", "Do"]
输出: 3
解释:
我们可以有如下三种方式:
"CatMat" = "Cat" + "Mat"
"CatMat" = "Ca" + "tM" + "at"
"CatMat" = "C" + "at" + "Mat"
样例2
输入:
"a"
[]
输出: 0
//递归方式:题目要求忽略大小写,所以要100%AC需要,将字符串提前都转换成小写
#ifndef C683_H
#define C683_H
#include<iostream>
#include<unordered_set>
#include<string>
using namespace std;
class Solution {
public:
/*
* @param : A string
* @param : A set of word
* @return: the number of possible sentences.
*/
int wordBreak3(string& s, unordered_set<string>& dict) {
// Write your code here
if (s.empty() || dict.empty())
return 0;
int num = 0;
helper(s, dict, 0, num);
return num;
}
//pos表示字符串的当前位置,num表示可以组成语句的个数
void helper(string &s, unordered_set<string>& dict, int pos,int &num)
{
if (pos == s.size())//已经遍历完字符串,num++
{
num++;
return;
}
string str;
//从当前位置向后取字符串,若存在于set中,改变pos的值,深度搜索
for (int j = 1; j <= s.size() - pos; ++j)
{
str = s.substr(pos, j);
if (dict.find(str) != dict.end())
{
helper(s, dict, pos + j, num);
}
}
}
};
#endif

浙公网安备 33010602011771号