私がより明確だと思う方法で注文のルールを述べさせてください。
文字列Aが文字列Bより大きい場合
- A is longer than B
OR
- A and B are the same length and A is lexicographically greater than B
ルールの言い換えが正しければ、O(n ^ 2)時間とO(n)空間で実行されるソリューションがあると思います。私の解決策は、入力文字列に一意の文字があるのと同じ数の有効なサブシーケンスに最も長い文字があるという観察に基づく欲張りアルゴリズムです。私はこれをGoで書きましたが、うまくいけば、コメントはアルゴリズムを説明するのに十分です。
func findIt(str string) string {
// exc keeps track of characters that we cannot use because they have
// already been used in an earlier part of the subsequence
exc := make(map[byte]bool)
// ret is where we will store the characters of the final solution as we
// find them
var ret []byte
for len(str) > 0 {
// inc keeps track of unique characters as we scan from right to left so
// that we don't take a character until we know that we can still make the
// longest possible subsequence.
inc := make(map[byte]bool, len(str))
fmt.Printf("-%s\n", str)
// best is the largest character we have found that can also get us the
// longest possible subsequence.
var best byte
// best_pos is the lowest index that we were able to find best at, we
// always want the lowest index so that we keep as many options open to us
// later if we take this character.
best_pos := -1
// Scan through the input string from right to left
for i := len(str) - 1; i >= 0; i-- {
// Ignore characters we've already used
if _, ok := exc[str[i]]; ok { continue }
if _, ok := inc[str[i]]; !ok {
// If we haven't seen this character already then it means that we can
// make a longer subsequence by including it, so it must be our best
// option so far
inc[str[i]] = true
best = str[i]
best_pos = i
} else {
// If we've already seen this character it might still be our best
// option if it is a lexicographically larger or equal to our current
// best. If it is equal we want it because it is at a lower index,
// which keeps more options open in the future.
if str[i] >= best {
best = str[i]
best_pos = i
}
}
}
if best_pos == -1 {
// If we didn't find any valid characters on this pass then we are done
break
} else {
// include our best character in our solution, and exclude it for
// consideration in any future passes.
ret = append(ret, best)
exc[best] = true
// run the same algorithm again on the substring that is to the right of
// best_pos
str = str[best_pos+1:]
}
}
return string(ret)
}
O(n)時間でこれを実行できると確信していますが、解決策がわからなかったため、代わりにこれを投稿しました。