codeforces 889B

http://codeforces.com/contest/889/problem/B

题意:给你 n 个由小写字母组成的字符串,n个字符串全不相同,要求构造一个母串,使所有字符串在母串中出现的频率都是最大。如果母串有多种情况,输出长度最短的且字典序最小的;若没有这个母串,输出 NO;

题解:很容易可以看出每个字符最多只能出现一次,要是某个字符串中某个单词出现多次,肯定输出 no;

     那么考虑下答案的最长个数,每个小写字母出现一次,最长为26个字母,它的子串的最大数目为(1+26)* 26 / 2 = 351;

     那么只要 n 大于351 直接 no;接下来 n 只有 351 要怎么暴力就怎么暴力了。

        (写着写着突然想到,好像自己写烦了,若一个字符串中某个字符有后继,那么这个字符的后继就是唯一的,遍历每个字符串,若字符的后继有冲突,则 no)

  

下面是写烦的代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<set>
using namespace std;
string str[400];
int isv[400];
set<string> se;
bool isok(string s1)
{
    if( s1.size() > 26 ) return false;
    set<char>ch; 
    for(int i = 0; i < s1.size(); ++i) ch.insert(s1[i]);
    if(s1.size()!=ch.size()) return false;
    return true;
}
int solve(string s1, string s2)
{
    if( s1.find(s2) != std::string::npos) return 1;
    if( s2.find(s1) != std::string::npos) return 2;
    set<char>ch; 
    for(int i = 0; i < s1.size(); ++i) ch.insert(s1[i]);
    for(int i = 0; i < s2.size(); ++i) ch.insert(s2[i]);
    int len = s1.size() + s2.size() - ch.size();
    if(!len) return 3;
    int i1, i2; string sss;
    i1 = s1.size()-len; i2 = 0; sss = s1.substr(0, s1.size()-len);
    while(i1 < s1.size() && s1[i1]==s2[i2]) ++i1, ++i2;
    if(i1==s1.size()) 
    {
        se.insert(sss+s2);
        return 4;
    }
    i1 = 0; i2 = s2.size()-len; sss = s2.substr(0, s2.size()-len);
    while(i2 < s2.size() && s1[i1]==s2[i2]) ++i1, ++i2;
    if(i2==s2.size())
    {
        se.insert(sss+s1);
        return 4;
    }
    return 5;
}
int main (void)
{
    ios::sync_with_stdio(false);
    int n; cin >> n;
    if(n > 27*13)
    {
        cout<<"NO";
        return 0;
    }
    for(int i = 1; i <= n; ++i)
    {
        cin >> str[i];
        if( !isok(str[i]) )
        {
            cout<<"NO";
            return 0;
        }
    }
    int top = n;
    while(true)
    {
        memset(isv, 0x00, sizeof(isv));
        for(int i = 1; i <= top; ++i)
        {
            if(isv[i]) continue;
            for(int j = i+1; j <= top; ++j)
            {
                if(isv[j]) continue;
                int c = solve(str[i], str[j]);
                if(c==1) isv[j] = 1;
                else if(c==2) isv[i] = 1;
                else if(c==4) isv[i] = isv[j] = 1;
                else if(c==5)
                {
                    cout<<"NO";
                    return 0;
                }
                if(isv[i]==1) break;
            }
        }
        if(se.empty()) break;
        int to = 0;
        for(int i = 1; i <= top; ++i)
        {
            if(!isv[i]) str[++to] = str[i];
        }
        set<string>::iterator it;
        for(it = se.begin(); it!=se.end(); ++it) str[++to] = *it;
        se.clear();
        top = to;
    }
    for(int i = 1; i <= top; ++i)
    {
        if(!isv[i]) se.insert( str[i] );
    }
    set<string>::iterator it;
    for(it = se.begin(); it!=se.end(); ++it) cout << (*it);
} 
原文地址:https://www.cnblogs.com/lkcc/p/7846803.html