Hackerrank:Yet Another KMP Problem

来源:互联网 发布:java中的设计模式 编辑:程序博客网 时间:2024/05/17 01:32

Yet Another KMP Problem

locked
by Stonefeang

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_backconst 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);#endifsolve();return 0;}





0 0
原创粉丝点击