UVa 10391

题意

按字典序输入一些单词, 查找单词是否是由两个单词复合而成的并将复合单词输出
例如 ab + normal = abnormal

思路

vector< string> 存下string
题给数据范围120,000单词, 全部暴力枚举一遍复杂度肯定高了
考虑到因为输入是按字典序的
那么可以记录下每个字母开头的下标范围
( 这里用到两个标记数组 m[30], n [30] )
WA了几次, 最后发现是因为查找输出顺序有误
最后用map标记了一下 , 统一输出就AC了


AC之后学习网上题解的大多数方法用的是hash函数
还有 .substr() 枚举拆分字符串, 复杂度也在可控范围内

记录

C++ primer上关于string搜索函数 .find()
这里搜索返回值的数据类型是 size_type 即 size_t

//在str当中查找第一个出现的str2,找到则返回出现的位置,否则返回结尾
    string str ("I am an acmer!");
    string str2 ("acmer");
    size_t found = str.find(str2);
    if (found!=std::string::npos)
        cout << "Find " << str2 << " at : " << found << endl;

AC代码

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include<algorithm>
#include <cstring>
#include <map>

using namespace std;

vector<string> vec;
map<int,int> mrk;
int m[30],n[30];

int main()
{
    int num = 0, i = 0, j;
    string s;
    std::size_t f;
    memset(n,0,sizeof(n));
    while( cin >> s ){
        vec.push_back(s);
        num++;
        if( m[s[0]-'a'] == 0 )
            m[s[0]-'a'] = num;
        n[s[0]-'a']++;
    }
    for( i = 0; i < num; i++ ){
        int len = vec[i].length();
        int x = vec[i][0]-'a';
        //cout <<"first" <<  i << ' ' << m[x]+n[x]-1-1 << ' ' << endl;
        for( j = i; j < m[x]+n[x]-1; j++ ){
            f = vec[j].find(vec[i]);
            if(f != std::string::npos){
                int xx = vec[j][len] - 'a';
                if( m[xx] == 0 )
                    continue;
                //cout << "second" << m[xx]-1 << ' ' << m[xx]+n[xx]-1-1 << endl;
                for( int k = m[xx]-1; k < m[xx]+n[xx]-1; k++ )
                    if( vec[i] + vec[k] == vec[j] && !mrk.count(j)){
                        pair<int,int> p(j,1);
                        mrk.insert(p);
                        break;
                    }
            }
        }
    }
    for( i = 0; i < num; i++ )
        if( mrk.count(i) )
            cout << vec[i] << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/JinxiSui/p/9740633.html