只需构造出W或P中的一个即可用二分查找构造另一个。
P的构造相对容易一些,给定要检验的字符串x,遍历其中的字符,根据当前字符计算在当前位置处小于给字符的字符串总数(此步可记忆化存储结果)即可。
最终结果是turnthestarson
注:因使用cache装饰器作记忆化搜索,以下代码为Python 3。只需构造出W或P中的一个即可用二分查找构造另一个。
P的构造相对容易一些,给定要检验的字符串x,遍历其中的字符,根据当前字符计算在当前位置处小于给字符的字符串总数(此步可记忆化存储结果)即可。
最终结果是turnthestarson
注:因使用cache装饰器作记忆化搜索,以下代码为Python 3。
from collections import Counter
from functools import *
phrase="thereisasyetinsufficientdataforameaningfulanswer"
N=15
counts=sorted(Counter(phrase).most_common())
letters="".join(x for x,_ in counts)
amounts=[y for _, y in counts]
f=lambda a,i:tuple(sorted(v-1 if u==i else v for u,v in enumerate(a) if (u==i and v>1) or (u!=i and v>0)))
@cache
def arrange(a,n):
return 1 if n==0 else 1+sum(arrange(f(a,i), n-1) for i,c in enumerate(a))
def P(x):
s=""
t=list(amounts)
pos=1
for c in x:
k=letters.find(c)
pos+=1+sum(arrange(f(t,i),N-len(s)-1) for i in range(k) if t[i]!=0)
s+=c
t[k]-=1
return pos-1
def W(m):
s=""
t=list(amounts)
while P(s)!=m:
i=len(t)-1
while i>=0 and (t[i]==0 or P(s+letters[i])>m):
i-=1
s+=letters[i]
t[i]-=1
return s
print(W(P("legionary")+P("calorimeters")-P("annihilate")+P("orchestrated")-P("fluttering")))
|