Ranking (as of 2013-06-15): 189 out of 281
Language: C++
/* Uva 11027 - Palindromic Permutation To build using Visual Studio 2008: cl -EHsc -O2 palindromic_permutation.cpp */ #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; /* Count the number of occurrences of each lowercase letter in a given string: For a string of even length, all of the number of occurrences should be even. For a string of odd length, all but one of the number of occurrences should be even. Take the half of the letters from the string and generate permutation. */ const int nr_letters = 26; // number of lowercase letters const int length_max = 30; long long factorials[length_max / 2 + 1]; // factorials[i] is i! void generate_factorials() { factorials[0] = 1; for (int i = 1; i <= length_max / 2; i++) factorials[i] = factorials[i - 1] * i; } int get_half_palindrome(const char* s, int half_palindrome_letters[], char half_palindrome[]) { int length = 0; for ( ; *s; s++, length++) half_palindrome_letters[*s - 'a']++; int i_odd_letter = -1; // index of the letter that has an odd number of occurrences for (int i = 0; i < nr_letters; i++) { if (half_palindrome_letters[i] & 1) { if (!(length & 1) || i_odd_letter != -1) return -1; i_odd_letter = i; } half_palindrome_letters[i] >>= 1; } int half_palindrome_length = 0; // append the letters half the numbers of original strings // in alphabetical order for (int i = 0; i < nr_letters; i++) if (half_palindrome_letters[i]) { for (int j = half_palindrome_letters[i]; j; j--) half_palindrome[half_palindrome_length++] = 'a' + i; } // append the letter that has an odd number of occurrences if (i_odd_letter != -1) half_palindrome[half_palindrome_length++] = 'a' + i_odd_letter; half_palindrome[half_palindrome_length] = '\0'; return half_palindrome_length; } int generate_n_th_palindrome(long long n, int length, int letters[], char palindrome[]) { /* For the number of permutations of words, see "Multinomial theorem - Wikipedia, the free encyclopedia": ... the multinomial coefficient is also the number of distinct ways to permute a multiset of n elements, and k(i) are the multiplicities of each of the distinct elements. ... */ int i, j; long long numerator = factorials[length], denominator = 1; for (i = 0; i < nr_letters; i++) if (letters[i]) denominator *= factorials[letters[i]]; if (n > numerator / denominator) return -1; for (i = 0; i < length; i++) { numerator /= length - i; for (j = i; j < length; ) { char c = palindrome[j]; int k = letters[c - 'a']; long long p = numerator / (denominator / k); if (n <= p) { denominator /= k; letters[c - 'a']--; // insert c at palindrome[i] memmove(&palindrome[i + 1], &palindrome[i], sizeof(char) * (j - i)); palindrome[i] = c; break; } n -= p; j += k; } } return length; } int get_n_th_palindrome(int n, int palindrome_length, int half_palindrome_length, int half_palindrome_letters[], char half_palindrome[], char palindrome[]) { int permutation_length = palindrome_length - half_palindrome_length; if (generate_n_th_palindrome(n, permutation_length, half_palindrome_letters, half_palindrome) == -1) return -1; // generate the n-th palindrome memcpy(palindrome, half_palindrome, half_palindrome_length); for (int i = 0, j = palindrome_length - 1; i < permutation_length; i++, j--) palindrome[j] = palindrome[i]; palindrome[palindrome_length] = '\0'; return palindrome_length; } int main() { generate_factorials(); int nr_cases; scanf("%d", &nr_cases); for (int c = 1; c <= nr_cases; c++) { char s[length_max + 1]; int n; scanf("%s %d", s, &n); printf("Case %d: ", c); char half_palindrome[length_max / 2 + 1], palindrome[length_max + 1]; int half_palindrome_letters[nr_letters]; // half_palindrome_letters[i] is the number of occurrences of // letter ('a' + i) in the half_palindrome memset(half_palindrome_letters, 0, sizeof(half_palindrome_letters)); int half_palindrome_length = get_half_palindrome(s, half_palindrome_letters, half_palindrome); int palindrome_length = (half_palindrome_length > 0) ? get_n_th_palindrome(n, strlen(s), half_palindrome_length, half_palindrome_letters, half_palindrome, palindrome) : -1; printf("%s\n", ((palindrome_length > 0) ? palindrome : "XXX")); } return 0; }
No comments:
Post a Comment