Yet Another KMP Problem
![](https://secure.gravatar.com/avatar/8cbb96bef69049403e92cdeccdad7219?d=https://d3rpyts3de3lx8.cloudfront.net/hackerrank/assets/gravatar.jpg&s=200)
This challenge uses the famous KMP algorithm. It isn't really important to understand how KMP works, but you should understand what it calculates.
A KMP algorithm takes a string, S , of length N as input. Let's assume that the characters in S are indexed from 1 to N ; for every prefix of S , the algorithm calculates the length of its longest valid border in linear complexity. In other words, for every i (where 1≤i≤N ) it calculates the largest l (where 0≤l≤i−1 ) such that for every p (where 1≤p≤l ) there is S[p]=S[i−l+p] .
Here is an implementation example of KMP:
kmp[1] = 0;
for (i = 2; i <= N; i = i + 1){
l = kmp[i - 1];
while (l > 0 && S[i] != S[l + 1]){
l = kmp[l];
}
if (S[i] == S[l + 1]){
kmp[i] = l + 1;
}
else{
kmp[i] = 0;
}
}
Given a sequence x1,x2,…,x26 , construct a string, S , that meets the following conditions:
- The frequency of letter ' a ' in S is exactly x1 , the frequency of letter ' b ' in S is exactly x2 , and so on.
- Let's assume characters of S are numbered from 1 to N , where ∑i=1nxi=N . We apply the KMP algorithm to S and get a table, kmp , of size N . You must ensure that the sum of kmp[i] for all i is minimal.
If there are multiple strings which fulfill the above conditions, print the lexicographically smallest one.
Input Format
A single line containing 26 space-separated integers describing sequence x .
Constraints
- The sum of all xi will be a positive integer ≤106 .
Output Format
Print a single string denoting S .
Sample Input
2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Sample Output
aabb
Explanation
The output string must have two ' a ' and two ' b '. There are several such strings but we must ensure that sum of kmp[i] for all 1<=i<=4 is minimal. See the figure below:
The minimum sum is 1 . Among all the strings that satisfy both the condition, "aabb" is the lexicographically smallest.
题意是给出一个字符串各个字符的出现次数,要使得一个,这个字符的kmp数组的和最小,还要字典序最大。
kmp数组的和最小,其实就是前缀不想等,这样就要把出现次数最少的那个字符放到第一个,然后考虑各种情况,如果这个字符字典序在后面,那直接按字典序排好,输出。
如果这个字符本身在字典序第一位,那么考虑让这个字符与其他字符交叉输出使得前缀字符不相等。
代码:
#pragma warning(disable:4996)
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define INF 0x3fffffff
#define repp(i, n, m) for (int i = n; i <= m; i++)
#define rep(i, n, m) for (int i = n; i < m; i++)
#define sa(n) scanf("%d", &(n))
#define mp make_pair
#define ff first
#define ss second
#define pb push_back
const int maxn = 1e6 + 5;
const ll mod = 1000000;
const double PI = acos(-1.0);
vector< pair <int, char> > v;
bool cmp(const pair<int, char>&a, const pair<int, char>&b)
{
return a.ss < b.ss;
}
void solve()
{
int i, j, k;
rep(i, 0, 26)
{
sa(k);
if (k == 0)continue;
v.pb(mp(k, i + 'a'));
}
sort(v.begin(), v.end());
sort(v.begin() + 1, v.end(), cmp);
if (v.size() == 1)
{
rep(i, 0, v[0].ff)
{
printf("%c", v[0].ss);
}
printf("\n");
return;
}
int le = 0, ri = 1;
//buf[cur++] = v[le].ss, v[le].ff--;
printf("%c", v[le].ss);
v[le].ff--;
if (v[le].ss > v[ri].ss)
{
sort(v.begin(), v.end(), cmp);
rep(i, 0, v.size())
{
rep(j, 0, v[i].ff)
{
printf("%c", v[i].ss);
}
}
printf("\n");
}
else
{
while (ri < v.size())
{
if (v[le].ff)
{
v[le].ff--;
printf("%c", v[le].ss);
}
if (v[ri].ff)
{
v[ri].ff--;
printf("%c", v[ri].ss);
if (v[ri].ff == 0)
{
ri++;
}
}
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("i.txt", "r", stdin);
freopen("o.txt", "w", stdout);
#endif
solve();
return 0;
}