阿里巴巴2018届应届生招聘研发工程师CC++考试-编程题一

题目

描述

给定一个字符串  S 和有效单词的字典D,请确定可以插入到 S中的最小空格数,使得最终的字符串完全由D中的有效单词组成,并输出解。    
如果没有解则应该输出 n/a    

输入

第一行为字符串 S,第二行为词典单词数目 n,接下来 n行,每行为一个单词  

输出

只有一行,为插入最少空格后的字符串

Example

Input

ilikealibaba
6
i
like
ali
liba
baba
alibaba  

Output

i like alibaba

题解

DFS

  • 深搜所有符合要求的解,过程剪枝
  • 选择最优解输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <bits/stdc++.h>

using namespace std;

string newStr;

void mincut(const string& str, const set<string>& dict,int s,string sstr)
{
if(s==str.length()&&sstr.length()<newStr.length())
{
newStr=sstr;
return;
}
for(auto it=dict.begin();it!=dict.end();it++)
{
string t=*it;
int i;
for(i=0;i<t.length();++i)
if(t[i]!=str[i+s])break;
if(i==t.length()&&s+i<=str.length())
{
if(s) t=" "+t;
mincut(str,dict,s+i,sstr+t);
}
}
}

int main(int argc, const char * argv[])
{
string strS;
string dictStr;
int nDict;
set<string> dict;

cin>>strS;
cin>>nDict;
for (int i = 0; i < nDict; i++)
{
cin>>dictStr;
dict.insert(dictStr);
}

newStr=strS+strS;

mincut(strS, dict,0,string());

if(newStr.length())
cout<<newStr;
else
cout<<"n/a";
return 0;
}

二分法

  • 把字典按长度降序排序
  • 匹配区间为 (s, e)
  • 若 s==e ,则匹配成功,返回 true
  • 在区间 (s, e) 内中匹配最长单词所在位置
  • 每找到一个位置 pos ,则根据这个单词把区间 (s, e) 分为 (s, pos).(pos, pos+dict[i].length).(pos+dict[i].length, e) 三部分
  • 对 前.后 两部分进行同样的操作
  • 若 前.后 两部分匹配成功,则此区间匹配成功,返回 true
  • 若匹配不成功,则寻找下个位置
  • 若无下个位置则匹配次长单词
  • 若没有匹配成功,则返回 false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>

using namespace std;

bool comp(const string &s1,const string &s2)
{
return s1.length()>s2.length();
}

map<int,int>newStr;
bool mincut(const string& str, const vector<string>& dict,int s,int e)
{
if(s==e)return 1;
for(int i=0;i<dict.size();++i)
{
int pos=s;
while(pos+dict[i].length()<=e&&(pos=str.find(dict[i],pos))!=string::npos)
{
newStr[pos]=i;
if(mincut(str,dict,s,pos)&&mincut(str,dict,pos+dict[i].length(),e))
return 1;
newStr.erase(pos);
}
}
return 0;
}


int main(int argc, const char * argv[])
{
string strS;
int nDict;
cin>>strS;
cin>>nDict;
vector<string> dict(nDict);
for (int i = 0; i < nDict; i++)
{
cin>>dict[i];
}
sort(dict.begin(),dict.end(),comp);
if(!mincut(strS, dict,0,strS.length()))
cout<<"n/a";
else
{
cout<<dict[newStr[0]];
auto it=newStr.begin();
for(it++;it!=newStr.end();it++)
cout<<" "<<dict[it->second];
}
return 0;
}