Uva10191 复合词

题目描述:

给出一个按字母序排列的单词列表,找到其中存在的复合词。复合词的定义是由单词列表中其他的两个单词拼接而成。所有单词均为小写。

Uva10191 复合词_第1张图片

思路:

如果直接两层遍历所有的单词组合,看他们加在一起是否是单词列表中的一个,在输入如此大的情况下,肯定会超时。我的做法是,定义vector svec[26],将单词按首字母分别存放在svec[i]里,对一个复合词,他的前半部分单词首字母和他相同,先在svec[i]里找前半部分单词,如果存在那么再去找后半部分单词,根据后半部分单词的首字母容易定位到是在svec[j]查找。

​需注意的细节:输出的复合词不重复出现,故用set保存答案,同时也完成了按字母序输出的要求。

代码:

"点击查看代码"

#include 
#include 
#include 
#include 
#include 
using namespace std;

bool preword(string s1, string s2){ //判断s1是否是s2的前缀 
    if(s1.size() > s2.size()) return false;
    int i = 0;
    for(; i < s1.size(); ++i){
        if(s1[i] != s2[i]) break;
    }
    if(i == s1.size()) return true;
    else return false; 
}

int main()
{
    string s;
    map
    
      smap;
    vector
     
       svec[26];
    string compound;
    set
      
        ans;
    while(cin >> s){
        svec[s[0]-'a'].push_back(s); //按首字母分别存放
    }
    for(int i = 0; i < 26; ++i){     //对a~z的每一个首字母
        for(int j = 0; j < svec[i].size(); ++j){
            for(int k = 0; k < j; ++k){  //因为输入是按字母序输入的,所以svec[i][j]是在svec[i][j]后面的单词
                if(preword(svec[i][k], svec[i][j])){ //如果k是j的前缀
                    string s = svec[i][j].substr(svec[i][k].size(), svec[i][j].size() - svec[i][k].size());   //再考虑后半部分字串
                    for(int m = 0; m < svec[s[0]-'a'].size(); ++m){ //看后半部分字串是否是svec[s[0]-'a']中的单词
                        if(s.compare(svec[s[0]-'a'][m]) == 0) ans.insert(svec[i][j]);
                    }
                }
            }
        }
    }
    for(auto c : ans){
        cout << c << "\n";
    }
}


​   
      
     
    

上述做法的比较麻烦,效率不高,其实还有更好的做法,对每个单词做拆分,利用map来对拆分的子串判断是否是输入之中的单词。代码如下:

"点击查看代码"

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 120002;
string sarr[maxn];
int main()
{
    set
    
      ans;
    int cnt = 0;
    map
     
       smap;
    while(cin >> sarr[cnt]){
        smap[sarr[cnt]] = 1;
        ++cnt;
    }
    for(int i = 0; i < cnt; ++i){

        for(unsigned j = 0; j < sarr[i].size(); ++j){
            string a = sarr[i].substr(0, j+1);
            if(!smap.count(a)) continue;
            string b = sarr[i].substr(j+1);
            if(!smap.count(b)) continue;
            ans.insert(sarr[i]); break;
        }
    }
    for(auto c : ans)
        cout << c << "\n";
}

     
    

你可能感兴趣的:(Uva10191 复合词)