ABC 268 D - Unique Username
重実装問題を募集したら教えてもらったので解きました。解けてうれしい。
考察
まず
ただ、アンダースコアを入れる個数が1以上なので、そのパターンを列挙した数も掛け合わせる必要があります。アンダースコアを入れるパターンをどうやって列挙するのか悩んだのですが、文字列の長さに上限があるので、各
文字列は最大16文字までなので、たとえばベースが10文字ならあと6文字アンダースコアを入れることができます。仮に
ここまでわかれば実装できそう。
実装
以下のようになりました。
import kotlin.system.exitProcess
fun main() {
val (n, m) = readln().split(" ").map { it.toInt() }
val s = MutableList(n) {
readln()
}
val t =(1..m).map { readln() }.toSet()
// 順列
val permutation = Permutation(s)
permutation.forEach {
val x = it.joinToString("_")
if(x.length > 16 || x.length < 3) {
println(-1)
exitProcess(0)
}
if(x !in t) {
println(x)
exitProcess(0)
}
val rest = 16 - x.length
rec(rest, it, t, IntArray(n - 1) { 1 }, 0)
}
println(-1)
}
private fun rec(maxCount: Int, list: MutableList<String>, t: Set<String>, array: IntArray, current: Int) {
if(current > maxCount) {
return
} else {
val s = join(list, array)
if(s !in t) {
println(s)
exitProcess(0)
}
}
for(i in array.indices) {
array[i]++
rec(maxCount, list, t, array, current + 1)
array[i]--
}
}
private fun join(list: MutableList<String>, array: IntArray): String {
val sb = StringBuilder()
for(i in list.indices) {
val s = list[i]
sb.append(s)
if(i != array.size) {
sb.append("_".repeat(array[i]))
}
}
return sb.toString()
}
class Permutation<T>(private val list: MutableList<T>) {
private val queue = ArrayDeque(list)
fun forEach(action: (MutableList<T>) -> Unit) {
forEach(0 ,0, action)
}
private fun forEach(count: Int, layer: Int, action: (MutableList<T>) -> Unit) {
if(count == list.size) {
action(list)
return
}
for(i in count until list.size) {
val elem = queue.removeFirst()
list[layer] = elem
forEach(count + 1, layer + 1, action)
queue.add(elem)
}
}
}
Permutationはこの問題を解くために作ってみました。
Permutationがあれば、あとはアンダースコアを配分するところが実装できればいけますね。これは再帰で実装しています。
exitProcess(0)
とか出てくるのがちょっと気持ち悪いですね… Permutationがinline化されていなくて、main関数自体から抜けるためのreturnができなかったためです。
このPermutationは適宜手を加えていきたいところです。
(執筆時間: 18分3秒)
Discussion