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;
}
全部评论

相关推荐

杨柳哥:这不是普通人,那这个钱的是天才
点赞 评论 收藏
分享
1 1 评论
分享
牛客网
牛客企业服务