I can see how to do it relatively efficiently. starting at the end of the string with only one character to 'choose' you so far have a rank of 0 (number 1, top rank) and have only 1 permutation. furthermore you have a total of 1 character to choose from and it's weight is 1, store this information somewhere
working backward through the string for each character, add this character to the list, if we let n be the number of permutations of our previous substring then
this substring will have n * (n+1) / k substrings where k is the count for the character we added at this point.
If you look at the alphabetical ordering of this character compared to the list of available characters then you take the sum of the counts of all of the characters that precede the current character alphabetically, multiply them by n. add this value to your current rank.
repeat this process and you should have a rank that is off by 1. add 1.
Example:
Let our string be apple
starting at e we have 1 permutation and 1 instance of e. we have rank 0
looking at l, we add p to the list of characters, giving it a count of 1
this means at this point there are 2 permutations
also, l is after e so we take 2 / 2 * 1 = 1
our rank is 1
next up is p, p is new too so it gets a count of 1
2 * 3 / 1 = 6 permutations for 'ple'
p is worse than both l and e so 6 / 3 * 2 = 4
our rank is now 5
a second p, p's count goes up to 2
6 * 4 / 2 = 12 permutations for 'pple'
again, p is worse than both l and e
12 / 4 * 2 = 6
our rank is now 11
finally the a, a is better than everybody
12 * 5 / 1 = 60
a is better than everyone, we add nothing to our rank
our final rank is 11
lets check the 'pple' substring because checking all 60 permutations for apple will be tiresome
elpp, eplp, eppl, lepp,
lpep, lppe, pelp, pepl,
plep, plpe, ppel, pple
that looks like a complete list of 12 to me, and with pple as the final element in that list, number 12, 11+1. Also, since apple starts with a, it can't lose rank so
apple must have the same rank, and it does.
since it works this time it must work every time
You can save a division by multiplying the new permutation by (n+1) after the rank at this point has been calculated. which is also preferrable because it means for the last (and thus largest) number of permutations you can avoid calculating that whole number, which could, in all probability wind up breaking your 64 bit barrier even if you're given a string with a rank that's under the limit.