Hackerrank:Yet Another KMP Problem

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, SS, of length NN as input. Let's assume that the characters in SS are indexed from 11to NN; for every prefix of SS, the algorithm calculates the length of its longest valid border in linear complexity. In other words, for every ii (where 1iN1≤i≤N) it calculates the largest ll (where 0li10≤l≤i−1) such that for every pp(where 1pl1≤p≤l) there is S[p]=S[il+p]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,,x26x1,x2,…,x26, construct a string, SS, that meets the following conditions:

  1. The frequency of letter 'aa' in SS is exactly x1x1, the frequency of letter 'bb' in SS is exactly x2x2, and so on.
  2. Let's assume characters of SS are numbered from 11 to NN, where i=1nxi=N∑i=1nxi=N. We apply the KMP algorithm to SS and get a table, kmpkmp, of size NN. You must ensure that the sum of kmp[i]kmp[i] for all ii is minimal.

If there are multiple strings which fulfill the above conditions, print the lexicographically smallest one.

Input Format

A single line containing 2626 space-separated integers describing sequence xx.

Constraints

  • The sum of all xixi will be a positive integer 106≤106.

Output Format

Print a single string denoting SS.

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 'aa' and two 'bb'. There are several such strings but we must ensure that sum of kmp[i]kmp[i] for all 1<=i<=41<=i<=4 is minimal. See the figure below:

The minimum sum is 11. 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;
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章