ABC324-C : Error Correction の珍回答供養 (Julia言語)
経緯(当時の思考過程)
久しぶりに競プロの問題でも解くかなと思って上の問題を開いた。
いやこれめちゃくちゃ難しいぞ。。。
とりあえず編集距離(レーベンシュタイン距離)くらいは知っていたので問題は「
- 普通に編集距離を計算すればよいのでは?:
かかるから無理そうO(N^2) -
から編集距離1以内の文字列を全て列挙しておけばよいのでは?:筋が良さそうと思ったが定数倍(アルファベットの数とか)がきつそうT
頭を抱えていたとき、謎の天啓が降りて来たのであった・・・
珍回答の解説
「ある文字列
まず、一般に
命題
解いた後、「文字列
ここで
-
のS 文字目を削除t^*+1 -
のT 文字目にt^*+1 のS 文字目を挿入t^*+1 -
のS 文字目をt^*+1 のT 文字目に置換t^*+1 -
のT 文字目をt^*+1 のS 文字目に置換t^*+1
の計4種である。ただし実際には「
-
のS 文字目を削除t^*+1 -
のS 文字目から最後までの部分文字列とt^*+2 のT 文字目から最後までの部分文字列を比較するt^*+1
-
-
のS 文字目をt^*+1 のT 文字目に置換t^*+1 -
のS 文字目から最後までの部分文字列とt^*+2 のT 文字目から最後までの部分文字列を比較するt^*+2
-
しかも、
ここから、「
このクエリを
コード供養😇
bs(ok, ng, S, T) = (m=(ok+ng)÷2; return ng-ok≡1 ? ok : (S[1:m]==T[1:m] ? bs(m, ng, S, T) : bs(ok, m, S, T)))
function main()
_, t = split(readline())
a, l = [], length(t)
for (n, s) in enumerate(readlines())
D = length(s) - l
(S, T) = D ≥ 0 ? (s, t) : (t, s)
m = bs(0, length(T) + 1, S, T)
S[m+2:end]==T[m+1+!(abs(D)>0):end] && push!(a, n)
end
println(length(a), '\n', join(a, " "))
end
main()
なぜ珍回答なのか
公式の解説を見るとなんとSを1回だけミスマッチを許して1から走査していた。
何!?それでは計算量
ここで問題の制約条件を見てみましょう
ん・・・?
🤔🤔🤔🤔🤔🤔🤔🤔
ということで解説の計算量はざっくり言って
二分探索の方も実は計算量の見積もりは間違っていて、
くらいだったようですね。
二分探索の解法は制約条件を全く見ていないことによる奇跡の(?)解法だったのでした。
余談
l = length(t)
をfor文の中で計算させるとTLEになってしまう。。。
文字列の長さの計算ってそんなに重い計算なんですかね?情報求ム
まとめ
日本語が読めてないせいで謎の回答にたどり着いてしまった。
制約条件には気を付けよう!
でも一生懸命考えた時間はプライスレス!(現実逃避)
Reference
とても良いめぐる式二分探索の解説記事です。おすすめ。
Discussion