题意:输入一个n,输入两个长度为2的字符串s, t,s和t只有可能是a b c这三个字符排列的情况。然后问,是否可以构造一个字符串,使得a b c出现次数均为n且该串中不包含s和t。
思路:首先我们可以将s和t的输入分为两种情况,第一种情况是s个t这两个字符串中的字符均是唯一的(也就是说不是重复某一字符,例如aa这种字符串)那一定会有形如
aaa...aaabbbb......bbbbbccccc.....ccccc的符合条件的字符串,因为这种字符串,每一个单元的内部(这里的单元指的是每一个重复单元,例如aaa.....aaaa)一定不会有非法序列
而各单元之间可以通过改变相对位置来使得s和t不存在。第二种情况是s和t当中至少有一个是由唯一的字符串组成的,这种情况下,前面说的那种字符串肯定不能用,此时
我们可以全排列abc,以abc为最小重复单元,这样一来,一定不会有类似aa,bb,cc这样的字符串(这个道理很容易想得通),而对于重复单元内部而言,至多只有一种非法序列的
可能,我们可以使非法序列交换位置就成了合法序列,由这些重复单元组成的字符串就是最终答案。如果两种情况都无法得出一个符合题意的答案,就输出NO。
PS.之前我一直有个点想不通,就是为什么这些都不成立能够推断出肯定没有其它任何解法。后面我再纸上稍微演算了一下,发现,如果是随意组合找结果,抛开以abc全排列为
最小单元重复的情况,其它任何可能的字符串都会导致整个字符串中出现aa..aa或者bbb.....bbbb或者cccc......cccccc,这就代表如果这种字符串是答案,要保证s和t不是
只由一个字符组成的字符串,那这样,肯定有个恒解,也就是我上面举的第一个例子。而如果第一个例子没有满足的,这种随意排列的肯定也无法满足,就只能在以abc全排列
为最小单元组成的字符串里找答案,如果找不到,那肯定就是没有别的解法了。
可能我总体说得有点抽象,若不明白,可以将各种情况自己一个一个剖开分解
代码没有什么妙处,主要是要理解解法
#include<bits/stdc++.h> using namespace std; string a, b; bool check(string x){ for(int i=0; i<x.length()-1; i++){ string temp = ""; temp += x[i]; temp += x[i+1]; if(temp == a || temp == b) return false; } return true; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; cin >> a >> b; vector<string> str; string sub1, sub2, sub3; for(int i=0; i<n; i++) sub1 += 'a', sub2 += 'b', sub3 += 'c'; str.push_back(sub1); str.push_back(sub2); str.push_back(sub3); do{ string temp = ""; temp += str[0]; temp += str[1]; temp += str[2]; if(check(temp)){ cout << "YES" << endl; cout << str[0] << str[1] << str[2] << endl; return 0; } }while(next_permutation(str.begin(), str.end())); vector<char> repeat; repeat.push_back('a'); repeat.push_back('b'); repeat.push_back('c'); do{ string temp = ""; temp += repeat[0]; temp += repeat[1]; temp += repeat[2]; string temp2 = ""; for(int i=0; i<n; i++) temp2 += temp; if(check(temp2)){ cout << "YES" << endl; cout << temp2 << endl; return 0; } }while(next_permutation(repeat.begin(), repeat.end())); cout << "NO" << endl; return 0; }