#問題
AtCoder Regular Contest 104 B問題より
#方針
1<=N<=5000という制約から、Sの部分文字列の全列挙自体は計算量は5000*(5000 + 1)//2と見積もられ、実行制限時間2秒を超えることはないと想定されます。しかし、実際に部分文字列を取り出そうとするとスライスの部分で余計な計算量を食うので、あらかじめi番目までにA, T, G, Cが何回登場したかを累積和を用いてA_rec, T_rec, G_rec, C_recに格納しておき、S[i:j]なる部分文字列についてそこから必要な値を用い、その部分文字列に何が何個含まれているかを調べます。そして(Aの個数)=(Tの個数)かつ(Gの個数)=(Cの個数)となれば良いので、それぞれ調べカウントします。
#TLEコード
Python
1from itertools import accumulate 2 3N, S = map(str, input().split()) 4N = int(N) 5 6A_rec = [0] * N 7T_rec = [0] * N 8G_rec = [0] * N 9C_rec = [0] * N 10 11for i in range(N): 12 if S[i] == 'A': 13 A_rec[i] += 1 14 elif S[i] == 'T': 15 T_rec[i] += 1 16 elif S[i] == 'G': 17 G_rec[i] += 1 18 elif S[i] == 'C': 19 C_rec[i] += 1 20A_rec = list(accumulate(A_rec)) 21T_rec = list(accumulate(T_rec)) 22G_rec = list(accumulate(G_rec)) 23C_rec = list(accumulate(C_rec)) 24 25def substring(S): 26 li = [] 27 for i in range(N): 28 for j in range(i + 1, N + 1): 29 if i > 0: 30 li.append([A_rec[j - 1] - A_rec[i - 1], T_rec[j - 1] - T_rec[i - 1], G_rec[j - 1] - G_rec[i - 1], C_rec[j - 1] - C_rec[i - 1]]) 31 elif i == 0: 32 li.append([A_rec[j - 1], T_rec[j - 1], G_rec[j - 1], C_rec[j - 1]]) 33 return li 34 35cnt = 0 36for el in substring(S): 37 if el[0] == el[1] and el[2] == el[3]: 38 cnt += 1 39 40print(cnt)
#質問
substringのところで二重ループを用いましたが、これはNの制約から直接的に実行時間超過に起因しているわけではなさそうであると推察しています。またそれ以外の処理については、全て線形時間で行っているので、これもまた大きな計算量を食っているようには思えません。実行はPypy3とPython3の両方で試しましたが、やはりPythonという言語の定数倍計算の処理の遅さがTLEの原因なのでしょうか。それとも、何か見落としている大きな計算がありますでしょうか。素人質問にて恐縮ですが、お力添え頂ける箇所がございましたら、ご教授のほどよろしくお願い申し上げます。
回答3件
あなたの回答
tips
プレビュー