- RNA consists of one strand (chain of ribonucleotides) most of the time,
and sometimes it can fold into the secondary structure. In this problem
we consider a simpler secondary form than in real life. In this form,
some pairs of complementary ribonucleotides build hydrogen bonds between
them and each ribonucleotide can build at most one bond. Each bond can
be represented as a pair of indices
(i,j) (i<j) of the string S that represents RNA. These indices indicate the positions of the symbols in S corresponding to these ribonucleotides.
Also, in the secondary structure one additional condition holds for each pair of hydrogen bonds(i1,j1) ,(i2,j2) , such thati1<i2 :
- they do not intersect
i1<j1<i2<j2
- they do not intersect
- or the second bond is inside the first one (
i1<i2<j2<j1 ).
import sys import math def norm(str1, str2): return math.fabs(int(str1) - int(str2)) def check_perfect(s): len_s = len(s) loops_tops = [] for i in range(1, len_s): if norm(s[i], s[i - 1]) == 1: loops_tops.append(i) if len(loops_tops) == 0: return False for start in loops_tops: step_right = 0 step_left = 1 move = True while move: right = int(s[start + step_right]) left = int(s[start - step_left]) if (right == 9) or (left == 9): move = False elif norm(left, right) != 1: move = False else: s[start + step_right] = '9' s[start - step_left] = '9' if ((start + step_right + 1) >= len_s) or ((start - step_left - 1) < 0): move = False step_right += 1 step_left += 1 new_s = [x for x in s if x != '9'] len_new_s = len(new_s) if len_new_s == 0: return True else: if len_new_s == len_s: return False else: return check_perfect(new_s) def check_perfect_if_one_hole(s): len_s = len(s) if len_s == 1: return True holed_tops = [] for i in range(2, len_s): if norm(s[i], s[i - 2]) == 1: holed_tops.append(i - 1) for hole in holed_tops: s1 = s.copy() del s1[hole] if check_perfect(s1): return True loops_tops = [] for i in range(1, len_s): if norm(s[i], s[i - 1]) == 1: loops_tops.append(i) if len(loops_tops) == 0: return False for start in loops_tops: step_right = 0 step_left = 1 move = True while move: right = int(s[start + step_right]) left = int(s[start - step_left]) if (right == 9) or (left == 9): move = False elif norm(left, right) != 1: if (start + step_right + 1) < len_s: if norm(int(s[start + step_right + 1]), left) == 1: s1 = s.copy() del s1[start + step_right] if check_perfect(s1): return True if (start - step_left - 1) > -1: if norm(right, int(s[start - step_left - 1])) == 1: s1 = s.copy() del s1[start - step_left] if check_perfect(s1): return True move = False else: s[start + step_right] = '9' s[start - step_left] = '9' if ((start + step_right + 1) >= len_s) or ((start - step_left - 1) < 0): move = False step_right += 1 step_left += 1 new_s = [x for x in s if x != '9'] len_new_s = len(new_s) if len_new_s == len_s: return False else: return check_perfect_if_one_hole(new_s) s0 = sys.stdin.readline() s0 = s0.replace('\n', '') s1 = s0.replace('U', '2') s2 = s1.replace('A', '1') s3 = s2.replace('G', '5') s4 = s3.replace('C', '6') s = list(s4) lens = len(s) if lens % 2 == 0: if check_perfect(s): print('perfect') else: print('imperfect') else: if check_perfect_if_one_hole(s): print('almost perfect') else: print('imperfect')
Hint:One could notice that the previous Dynamic Programming solution resembles the solutions for problems with bracket sequences. We could see a perfect string as a correct bracket sequence and we check the correctness of bracket sequences using stack!
So, to check if the string is perfect we iterate through bases and maintain a stack:
- If the current base is complementary to the base on top of the stack, then we pop from the stack.
- Otherwise, we put the current base into the stack.
time and does not fit into timelimit.
But the way to deal with it is quite easy. Let us perform the solution as in the case of the perfect string. We state that if the string is almost perfect then the base to delete is the middle base of the stack. We remove this base and check that the stack collapses. (In other words, we check that the stack has odd length and it holds a palindrome)
So, suitable solution is:
import sys def complementary(a, b): if (a == 'A' and b == 'U') or (a == 'U' and b == 'A') or (a == 'G' and b == 'C') or (a == 'C' and b == 'G'): return True else: return False def go_stack(str): stack = [] for i in str: if len(stack) > 0: if complementary(stack[-1], i): stack.pop() else: stack.append(i) else: stack.append(i) return stack s = sys.stdin.readline().strip() stack = go_stack(s) len_stack = len(stack) if len_stack == 0: print('perfect') else: if len_stack % 2 == 0: print('imperfect') else: stack.pop(int((len_stack - 1)/2)) stack2 = go_stack(stack) if len(stack2) == 0: print('almost perfect') else: print('imperfect')
Комментариев нет:
Отправить комментарий