068 D - String Equivalence¶
- created: 2022-11-30
- ご意見・ご要望はissue・プルリク用のGitHubまで
- 競技プログラミングのためのF#入門
- GitHub上の対応ディレクトリ
- 公式ページ, Panasonic 2020 D - String Equivalence
- 公式解説, PDF
解説1¶
- 下記方針に基づいた最終実装例
- 実装を見ると特に明確なように, 長さ
Nの標準形は長さN-1の文字列に一文字足して作られます. - 出題例をもとに特に小さい
Nで実験してもわかります. - 追加できる文字は
aを先頭に, 各文字列の中の最大の文字の一つ次までです.
ここまでの情報をもとにすれば素直に実装できます. まず補助関数を二つ作ります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
今回の問題の範囲では困らないためそのままにしているものの, succ 'z'の挙動が気になるなら適切に書き換えてください.
さて, 長さ2の標準形の一つabに対して長さ3の標準形を作りましょう. 関数mによってaからcまで追加できます. 文字の追加の仕方はいろいろあって文字列の連結で素直に後ろにつなげてもいいでしょう. ここでは文字列(.NETとしては文字の配列)を文字のリストにし, リストの連結もconsを使って前に追加します.
1 2 3 | |
長さ2の標準形はaaとabだから両方に作用させましょう.
1 2 3 | |
これで長さ3の標準形が得られました. しかしこれはchar list list listです. 実際に欲しいのはstring listで, char listをstring = char[]に変える必要もあります.
リストのネストを一つ減らすのはList.concatで, List.collect = List.map >> List.concatを使ってつなげて書けます. char list -> stringは.NETレベルのメソッドSystem.String.Concatを使います. リストはほしい文字列の逆になっているからList.revの処理も必要です.
これを再帰でまとめると次の解答が得られます.
1 2 3 4 5 6 7 8 9 10 | |
解説2: 末尾再帰¶
少し書き方を変えれば末尾再帰にできます. 結論だけ書くと次の通りです.
1 2 3 4 5 6 7 8 9 | |