結果
| 問題 |
No.1609 String Division Machine
|
| コンテスト | |
| ユーザー |
👑 SPD_9X2
|
| 提出日時 | 2021-05-10 23:50:15 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 319 ms / 2,000 ms |
| コード長 | 2,305 bytes |
| コンパイル時間 | 180 ms |
| コンパイル使用メモリ | 81,708 KB |
| 実行使用メモリ | 145,060 KB |
| 最終ジャッジ日時 | 2024-07-06 07:53:11 |
| 合計ジャッジ時間 | 5,324 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 37 |
ソースコード
"""
想定解v2 エラー解消
"""
import bisect
import sys
def LIS(lis):
seq = []
for c in lis:
ind = bisect.bisect_left(seq,c)
if ind == len(seq):
seq.append(c)
else:
seq[ind] = c
return len(seq)
alp = "abcdefghijklmnopqrstuvwxyz?"
cd = {} #文字→数字にする辞書型
for i in range(-1,26):
cd[alp[i]] = i
#N = int(input())
S = list(input())
#制約チェック
#assert N == len(S)
for i in S:
assert i in cd
N = len(S)
assert 1 <= N <= 10**5
#全て?の場合を処理する
allq = True #全て?かどうかのフラグ
for i in S:
if i != "?":
allq = False
break
if allq:
print ("a"*N)
sys.exit()
# dp[i][c] = i文字目以降で作れる最長増加部分列のうち、c以上で始まる物の最長。?は無視する
dpA = [[0] * 26 for i in range(N+1)]
for i in range(N-1,-1,-1):
nmax = 0 #dpA[i][c] の最大 (c > j)
for j in range(25,-1,-1):
dpA[i][j] = max(dpA[i+1][j] , nmax)
if cd[S[i]] == j:
dpA[i][j] = max(dpA[i][j] , nmax + 1)
nmax = max(nmax , dpA[i][j])
OLIS = max(dpA[0]) #?を無視した際のLIS
"""
for i in dpA:
print (*i)
print (OLIS)
"""
ans = []
dpB = [[0] * 26 for i in range(N+1)] #i文字目以前で作れるLISのうち、c以下で終る物の最長
for i in range(N):
if S[i] != "?": #?でない場合、置くものは一意
nc = cd[S[i]]
else: #?の場合、置ける辞書順最小の物を探索する
for c in range(26):
if c == 0:
if dpA[i+1][c+1] + 1 <= OLIS:
nc = c
break
elif c != 25:
if dpB[i-1][c-1] + dpA[i+1][c+1] + 1 <= OLIS:
nc = c
break
else: #25
if dpB[i-1][c-1] + 1 <= OLIS:
nc = c
break
else:
print ("error",file=sys.stderr)
sys.exit(1)
ans.append(alp[nc])
nmax = 0
for j in range(26):
dpB[i][j] = max(dpB[i-1][j] , nmax)
if nc == j:
dpB[i][j] = max(dpB[i][j] , nmax + 1)
nmax = max(nmax , dpB[i][j])
assert LIS(ans) == OLIS
print ("".join(ans))
SPD_9X2