F - Avoid K Palindrome 2 Editorial by en_translator
Enumerate all the strings obtained by permuting the characters of \(S\), and check if each of them contain a length-\(K\) palindrome as a substring.
One can enumerate the permutation of \(S\) with next_permutation
function in C++. One can also use itertools.permutations
function in Python, but it distinguishes the same character at different positions, so you need to remove duplicates appropriately. Also, if your language does not provide with such a standard function, you need to implement it by yourself. There are several known algorithms that enumerates permutations, which you can search for it online. One of the most famous ones is as follows.
The permutation of \(P=(P_1,P_2,\ldots,P_N)\) that comes right after \(P\) in lexicographical order is obtained as follows.
- Take the largest \(i\) \((1\leq i\leq N-1)\) with \(P_i<P_{i+1}\).
- For \(i\) in 1., take the largest \(j\) with \(P_i<P_j\).
- Swap \(P_i\) and \(P_j\).
- Reverse \(P_{i+1},P_{i+2},\ldots,P_N\).
By repeatedly applying this procedure against a sequence initially sorted in ascending order (until it becomes a globally descending sequence), all the permutations can be enumerated.
In this algorithm, one can enumerate all the permutations in \(O(N!)\) time. Therefore, the overall time complexity is \(O(N!\cdot(NK))\). Since \(10!\sim 3\times 10^6\), this is fast enough under the constraints of this problem. Thus, the problem has been solved.
Sample code in C++:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,k;
string s;
cin>>n>>k;
cin>>s;
vector<int>a;
for(int i=0;i<n;i++)a.push_back(((int)(s[i]-'a')));
sort(a.begin(),a.end());
int ans=0;
bool ok,flag;
while(true){
ok=true;
for(int i=0;i<=n-k;i++){
flag=true;
for(int j=0;j<k;j++){
if(a[i+j]!=a[i+k-1-j])flag=false;
}
if(flag)ok=false;
}
if(ok)ans++;
if(!next_permutation(a.begin(), a.end()))break;
}
cout<<ans<<endl;
return 0;
}
posted:
last update: