codeforces 889B - Restoration of string
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); }