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