问题描述:
给定一个字符串和一个单词字典(单词集合),请问是否可以把这个给定字符串分割成词典中存在的单词序列?并输出分割结果集。
据说这个问题是著名的google interview 问题。自从被google用来做面试问题后,许多公司都拿这个问题做面试问题。笔者最先是在
www.geeksforgeeks.org上看到这个问题,有兴趣的朋友可去这个网站寻找这个问题。
问题解决:
这个问题比较直观,相对解法也比较简单,我试着用你三种方法解决这个问题;
1. 暴力搜索(brute force search)
2. 递归解法
3. 动态规划
源代码如下:
#ifndef _RECURSIVE_SET_H_
#define _RECURSIVE_SET_H_
#include <iostream>
#include <string>
#include <map>
/*
* The implementation of brute force method for the problem of break word
*
*/
void BreakWordBrute( std::string& inputStr, std::map<std::string, bool >& dict, std::vector<std::string>& result )
{
int cur = 0;
for( int i = 0; i < inputStr.size(); )
{
int start = i;
for( int j = start + 1; j <= inputStr.size(); j++ )
{
std::string subStr = inputStr.substr( start, j - start );
std::map<std::string, bool>::iterator iter = dict.find( subStr );
if( iter != dict.end() )
{
start = j;
result.push_back( subStr );
}
}
if( start != i )
{
i = start;
}
else
{
i++;
}
}
std::cout << " the result of brute force method " << std::endl;
for( size_t i = 0; i < result.size(); i++ )
{
std::cout << result[i].c_str() << " ";
}
std::cout << std::endl;
}
/*
* The implementation of recursion of the problem of break word
*
*/
void BreakWordRecur( std::string& inputStr, int cur, std::map<std::string, bool >& dict, std::vector<std::string>& result )
{
if( cur >= inputStr.size() )
{
for( size_t i = 0; i < result.size(); i++ )
{
std::cout << result[i].c_str() << " ";
}
std::cout << std::endl;
return;
}
for( int i = cur + 1; i <= inputStr.size(); i++ )
{
std::string subStr = inputStr.substr( cur, i - cur );
std::map<std::string, bool>::iterator iter = dict.find( subStr );
if( iter != dict.end() )
{
result.push_back( subStr );
BreakWordRecur( inputStr, i, dict, result );
result.pop_back();
}
}
}
/*
* The implementation of recursion of the problem of break word
*
*/
bool BreakWordDP( std::string& inputStr, std::map<std::string, bool >& dict, std::vector<std::string>& result)
{
size_t len = inputStr.size();
int* table = new int[len + 1];
memset( table, 0x00, sizeof(int)*(len + 1) );
assert( table );
typedef std::map<std::string, bool>::iterator dictIter;
bool isExist = false;
for( int i = 1; i <= len; i++ )
{
if( 0 == table[i] )
{
std::string subStr = inputStr.substr( 0, i );
dictIter iter = dict.find( subStr );
if( iter != dict.end() )
{
table[i] = 1;
}
}
if( 1 == table[i] )
{
if( 1 == table[len] )
{
isExist = true;
break;
}
for( int j = i + 1; j <= len; j++ )
{
if( 0 == table[j] )
{
std::string subStr = inputStr.substr( i, j - i );
dictIter iter = dict.find( subStr );
if( iter != dict.end() )
{
table[j] = 1;
}
}
if( 1 == table[j] && len == j )
{
isExist = true;
break;
}
}
}
}
//output result by virtue of table memory
for( int i = 0; i <= len; )
{
int start = i;
while( 0 == table[start] )
{
start++;
}
if( 0 == i )
{
result.push_back( inputStr.substr( i, start - i ) );
}
else
{
result.push_back( inputStr.substr( i - 1, start - i + 1 ) );
}
i = start + 1;
}
delete [] table;
return isExist;
}
/*
* Test interface
*
*/
void BreakWord()
{
const char* str[] = {"i", "like", "sam", "sung", "samsung", "mobile", "ice",
"cream", "icecream", "man", "go", "mango", "mongo", "sweet"};
const char* input = "ilikesamsungmobile";
std::map<std::string, bool> dict;
size_t size = sizeof(str)/sizeof(str[0]);
for( size_t i = 0; i < size; i++ )
{
std::string strObj( str[i] );
std::map<std::string, bool>::iterator iter = dict.find(strObj);
if( iter != dict.end() )
{
continue;
}
else
{
dict.insert( std::make_pair( strObj, true ) );
}
}
std::vector<std::string> result;
BreakWordRecur( std::string(input), 0, dict, result );
result.clear();
BreakWordBrute( std::string(input), dict, result );
result.clear();
bool isExist = BreakWordDP( std::string(input), dict, result );
}
void TestSuite()
{
BreakWord();
}
#endif