possible sentences

possible sentences

http://www.nowcoder.com/questionTerminal/371e1d8f234c43eea90d96bd0f214b03

题解:

考察点: 深度优先搜索,字典树,剪枝

易错点:

本题的输入不是直接可用的,需要对输入进行字符串解析,同时由于输入带有空格,如果直接用会无法读入,建议使用按行进行读入。对于输入的解析,建议使用标记法,设置一个变量,当处于有效区域时,把标记为,当处于无效区域时,把标记为。这样保证有效部分能够很好的被解析出来。

本题的输出结果是按照字典序从大到小降序输出的。

方法一:深度优先搜索+剪枝

这题最直观的想法就是,对于字符串中每个位置,如果其前缀在集合中能找到,其可以以它为起点,往后找寻剩余部分是否在集合中,如果在集合中,则可以继续往后递归。这里加入一个剪枝,表示从是否满足条件,如果在进行以后发现剩余部分并没有满足条件的字符串,则可以进行剪枝,说明枚举这个位置已经没有意义了

#include "bits/stdc++.h"
using namespace std;
const int maxn=1e3+10;
int vis[maxn];
void Input(string &str,vector<string>&dict){  //读入数据
    string s,s1;
    getline(cin,s1);
    getline(cin,s);
    int flag=0;
    for(int i=0;i<s1.length();i++){
        if(!flag){
            if(s1[i]=='\"') flag=1;
            continue;
        }else{
            if(s1[i]=='\"'){
                flag=0;
            }else{
                str+=s1[i];
            }
        }
    }
    flag=0;
    string res="";
    for(int i=0;i<s.length();i++){
        if(!flag){
            if(s[i]=='\"') flag=1;
            continue;
        }else{
            if(s[i]=='\"'){
                flag=0;
                dict.push_back(res);
                res="";
            }else{
                res+=s[i];
            }
        }
    }
}
void dfs(string str,vector<string>dict,vector<string>&res,int pos,string t){
    if(pos==str.length()){
        res.push_back(t.substr(0,t.size()-1));
    }
    for(int i=pos;i<str.length();i++){
        string word=str.substr(pos,i-pos+1);
        if(find(dict.begin(),dict.end(),word)!=dict.end()&&!vis[i+1]){
            t.append(word).append(" ");
            int h=res.size();
            dfs(str,dict,res,i+1,t);
            if(h==res.size()) vis[i+1]=1;
            t.resize(t.size()-word.size()-1);
        }
    }
}
int main()
{
    string str="";
    vector<string>dict;
    Input(str,dict);
    memset(vis,0,sizeof(vis));
    vector<string>res;
    string t="";
    dfs(str,dict,res,0,t);
    sort(res.begin(),res.end());
    if(res.size()==0){
        cout<<"[]"<<endl;
    }else if(res.size()==1){
        cout<<"["<<res[0]<<"]"<<endl;
    }else{
        for(int i=res.size()-1;i>=0;i--){
            if(i==res.size()-1){
                cout<<"[";
                cout<<res[i];
            }else{
                cout<<", "<<res[i];
                if(i==0) cout<<"]"<<endl;
            }
        }
    }
    return 0;
}

方法二:字典树优化

在上述算法中,每次需要在集合中查询单词是否存在,如果集合很小还好,当集合非常大的时候,复杂度就会变得很高。可以引入字典树来进行优化。字典树由被称为前缀树,能在O(单词长度)的时间复杂度内查询单词是否存在与集合中,极大提升了查询的效率。关于字典树,网上资料很多,这里为同学们提供一份比较好用的模板

#include "bits/stdc++.h"
using namespace std;
const int maxn=1e3+10;
int vis[maxn];
int trie[maxn][26],tot;
bool End[maxn];
void insert(string str){
    int len=str.length(),p=1;
    for(int k=0;k<len;k++){
        int ch=str[k]-'a';
        if(trie[p][ch]==0) trie[p][ch]=++tot;
        p=trie[p][ch];
    }
    End[p]=true;
}
bool search(string str){
    int len=str.length(),p=1;
    for(int k=0;k<len;k++){
        p=trie[p][str[k]-'a'];
        if(p==0) return false;
    }
    return End[p];
}
void Input(string &str){  //读入数据
    string s,s1;
    getline(cin,s1);
    getline(cin,s);
    int flag=0;
    for(int i=0;i<s1.length();i++){
        if(!flag){
            if(s1[i]=='\"') flag=1;
            continue;
        }else{
            if(s1[i]=='\"'){
                flag=0;
            }else{
                str+=s1[i];
            }
        }
    }
    flag=0;
    string res="";
    for(int i=0;i<s.length();i++){
        if(!flag){
            if(s[i]=='\"') flag=1;
            continue;
        }else{
            if(s[i]=='\"'){
                flag=0;
                insert(res);
                res="";
            }else{
                res+=s[i];
            }
        }
    }
}
void dfs(string str,vector<string>&res,int pos,string t){
    if(pos==str.length()){
        res.push_back(t.substr(0,t.size()-1));
    }
    for(int i=pos;i<str.length();i++){
        string word=str.substr(pos,i-pos+1);
        if(search(word)&&!vis[i+1]){
            t.append(word).append(" ");
            int h=res.size();
            dfs(str,res,i+1,t);
            if(h==res.size()) vis[i+1]=1;
            t.resize(t.size()-word.size()-1);
        }
    }
}
int main()
{
    string str="";
    Input(str);
    memset(vis,0,sizeof(vis));
    vector<string>res;
    string t="";
    dfs(str,res,0,t);
    sort(res.begin(),res.end());
    if(res.size()==0){
        cout<<"[]"<<endl;
    }else if(res.size()==1){
        cout<<"["<<res[0]<<"]"<<endl;
    }else{
        for(int i=res.size()-1;i>=0;i--){
            if(i==res.size()-1){
                cout<<"[";
                cout<<res[i];
            }else{
                cout<<", "<<res[i];
                if(i==0) cout<<"]"<<endl;
            }
        }
    }
    return 0;
}
全部评论

相关推荐

2025-12-13 14:51
已编辑
井冈山大学 算法工程师
龙虾x:算法比你强的没有你美,比你美的…..算了已经没有比你美的了
工作两年想退休了
点赞 评论 收藏
分享
2025-12-08 16:04
门头沟学院 Java
本人本科末9,今年大三。大一大二一直玩,什么都没学到,在大学混日子混了两年,每天不是在打农就是在steam。大三开学时一个和自己玩的好的同学去实习了,才发现自己白白浪费了两年的时间,如果真不冲一下就真去京东,阿里,美团送外卖了今年9月份开始学Java,一开始一直跟着黑马视频看,后面发现看视频效率太低了,时间根本不够,就开始主要看文档和看书了。这几个月一直在学,真的尽力了,希望暑期前能找一份好点的实习。我简历上面的项目大多没有指标,但是实际上我是真没多少时间去做项目,我基本主要是动手只做了外卖和天机,黑马点评和12306我都是只是看了项目。主要是自己的时间真的不多,但是这样子自己的代码能力确实比较差。而且自己也没有做过实际的工程,我顶多用jmeter测试一下接口tps啥的,比如使用Redis管道提升了一点性能,减少Redis交互,这种值得写上去吗?需不需要具体到某些数字求求各位佬给一些建议,看看简历怎么优化?项目介绍是不是不够详细?没有具体到业务方面。项目会不会提到大致实现原理导致面试官一看简历就知道怎么实现就没有问的欲望?专业技能一些字段是不是要加粗,是不是写太啰嗦了?有没有必要压缩内容变成一页?两页的话是不是都要把两页填地满满的。
给秋招一个交代:一页简历最好,网上做的项目放面试官眼里都是玩具,简历上不需要强调有什么难点,记住就行防止真的问。然后背八股,多投多面试就行
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务