Problem:
Problem G
Do Geese See God? A palindrome is a sequence of characters which reads the same backward or forward. Famous ones include "dogeeseseegod" ("Do geese see God?"), "amoreroma" ("Amore, Roma.") and "risetovotesir" ("Rise to vote, sir."). An ancient sutra has been handed down through generations at a temple on Tsukuba foothills. They say the sutra was a palindrome, but some of the characters have been dropped through transcription. A famous scholar in the field of religious studies was asked to recover the original. After long repeated deliberations, he concluded that no information to recover the original has been lost, and that the original can be reconstructed as the shortest palindrome including all the characters of the current sutra in the same order. That is to say, the original sutra is obtained by adding some characters before, between, and/or behind the characters of the current. Given a character sequence, your program should output one of the shortest palindromes containing the characters of the current sutra preserving their order. One of the shortest? Yes, more than one shortest palindromes may exist. Which of them to output is also specified as its rank among the candidates in the lexicographical order. For example, if the current sutra is cdba and 7th is specified, your program should output cdabadc among the 8 candidates, abcdcba , abdcdba , acbdbca , acdbdca , cabdbac , cadbdac , cdabadc and cdbabdc . Input The input consists of a single test case. The test case is formatted as follows.  $S$ $k$ The first line contains a string $S$ composed of lowercase letters from ' a ' to ' z '. The length of $S$ is greater than 0, and less than or equal to 2000. The second line contains an integer $k$ which represents the rank in the lexicographical order among the candidates of the original sutra. $1 \leq k \leq 10^{18}$. Output Output the $k$-th string in the lexicographical order among the candidates of the original sutra. If the number of the candidates is less than $k$, output NONE . Though the first lines of the Sample Input/Output 7 are folded at the right margin, they are actually single lines. Sample Input 1 crc
1 Sample Output 1 crc Sample Input 2 icpc
1 Sample Output 2 icpci Sample Input 3 hello
1 Sample Output 3 heolloeh Sample Input 4 hoge
8 Sample Output 4 hogegoh Sample Input 5 hoge
9 Sample Output 5 NONE Sample Input 6 bbaaab
2 Sample Output 6 NONE Sample Input 7 thdstodxtksrnfacdsohnlfuivqvqsozdstwa
szmkboehgcerwxawuojpfuvlxxdfkezprodne
ttawsyqazekcftgqbrrtkzngaxzlnphynkmsd
sdleqaxnhehwzgzwtldwaacfczqkfpvxnalnn
hfzbagzhqhstcymdeijlbkbbubdnptolrmemf
xlmmzhfpshykxvzbjmcnsusllpyqghzhdvljd
xrrebeef
11469362357953500 Sample Output 7 feeberrthdstodxtksrnfacdjsohnlfuivdhq
vqsozhgdqypllstwausnzcmjkboehgcerzvwx
akyhswuojpfhzumvmlxxdfkmezmprlotpndbu
bbkblnjiedttmawsyqazekcftgshqbrhrtkzn
gaxbzfhnnlanxvphyfnkqmzcsdfscaawdleqa
xtnhehwzgzwhehntxaqeldwaacsfdsczmqknf
yhpvxnalnnhfzbxagnzktrhrbqhsgtfckezaq
yswamttdeijnlbkbbubdnptolrpmzemkfdxxl
mvmuzhfpjouwshykaxwvzrecgheobkjmcznsu
awtsllpyqdghzosqvqhdviuflnhosjdcafnrs
ktxdotsdhtrrebeef

Solution (Python):
from heapq import heappush, heappop

def solve():
    S = input()
    K = int(input())
    L = len(S)
    INF = 10**9
    cost = [[INF]*(L+1) for i in range(L+1)]
    cost[0][L] = 0
    ss = []
    que = [(0, 0, L)]
    while que:
        d, a, b = heappop(que)
        if cost[a][b] < d:
            continue
        ss.append((a, b))
        if a+1 == b:
            if d+1 < cost[a+1][b]:
                cost[a+1][b] = d + 1
            continue
        if S[a] == S[b-1]:
            if d+2 < cost[a+1][b-1]:
                cost[a+1][b-1] = d + 2
                if a+1 < b-1:
                    heappush(que, (d+2, a+1, b-1))
        else:
            if d+2 < cost[a+1][b]:
                cost[a+1][b] = d + 2
                if a+1 < b:
                    heappush(que, (d+2, a+1, b))
            if d+2 < cost[a][b-1]:
                cost[a][b-1] = d + 2
                if a < b-1:
                    heappush(que, (d+2, a, b-1))
    ln = min(cost[i][i] for i in range(L+1))
    ss.reverse()
    dp = [[0]*(L+1) for i in range(L+1)]
    for i in range(L+1):
        if cost[i][i] == ln:
            dp[i][i] = 1
    for a, b in ss:
        d = cost[a][b]
        r = 0
        if a+1 == b:
            if d+1 == cost[a+1][b]:
                r = dp[a+1][b]
        else:
            if S[a] == S[b-1]:
                if d+2 == cost[a+1][b-1]:
                    r = dp[a+1][b-1]
            else:
                if d+2 == cost[a+1][b]:
                    r += dp[a+1][b]
                if d+2 == cost[a][b-1]:
                    r += dp[a][b-1]
        dp[a][b] = r
    if dp[a][b] < K:
        print("NONE")
        return True
    SL = []; SR = []
    a = 0; b = L
    while a < b:
        if a+1 == b:
            assert cost[a][b]+1 == cost[a+1][b]
            SL.append(S[a])
            a += 1
            continue
        if S[a] == S[b-1]:
            assert cost[a][b]+2 == cost[a+1][b-1]
            SL.append(S[a])
            SR.append(S[b-1])
            a += 1; b -= 1
        elif S[a] < S[b-1]:
            c = (cost[a][b]+2 == cost[a+1][b])
            if c and K <= dp[a+1][b]:
                SL.append(S[a])
                SR.append(S[a])
                a += 1
            else:
                if c:
                    K -= dp[a+1][b]
                SL.append(S[b-1])
                SR.append(S[b-1])
                b -= 1
        else:
            c = (cost[a][b]+2 == cost[a][b-1])
            if c and K <= dp[a][b-1]:
                SL.append(S[b-1])
                SR.append(S[b-1])
                b -= 1
            else:
                if c:
                    K -= dp[a][b-1]
                SL.append(S[a])
                SR.append(S[a])
                a += 1
    SR.reverse()
    SL.extend(SR)
    print("".join(SL))
solve()