-
Notifications
You must be signed in to change notification settings - Fork 22
/
typewriter-monkey.py
65 lines (54 loc) · 2.02 KB
/
typewriter-monkey.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Copyright (c) 2015 kamyu. All rights reserved.
#
# Google Code Jam 2015 Round 1C - Problem B. Typewriter Monkey
# https://code.google.com/codejam/contest/4244486/dashboard#s=p1
#
# Time: O(K + L * S)
# Space: O(K + L)
#
def chars_before_repeat(s):
L = len(s)
# s = ABA, res => 2 because after 2 chars we can start a new pattern already
for i in xrange(1, L+1):
if s[i:] == s[0:L-i]:
return i
return L
def remaining_bananas(K, L, S, keyboard, target):
if L > S:
return 0
# Compute keyboard frequency
keyboard_freq = {}
for k in keyboard:
if k in keyboard_freq:
keyboard_freq[k] += 1
else:
keyboard_freq[k] = 1
# Make sure all necessary letters are there.
for k in target:
if k not in keyboard_freq:
return 0
# First, what is the maximum number of repeats?
spacing = chars_before_repeat(target)
ideal_bananas = (S-L)//spacing + 1
# Second, what is the average number of repeats?
keyboard_prob = {}
for k,v in keyboard_freq.iteritems():
keyboard_prob[k] = v / float(K)
if L == 1:
return ideal_bananas - S * keyboard_prob[target[0]]
# Sum up each probability of the string at position i matching the target by DP.
expected_bananas = 0.0
running_prob = [0.0 for i in xrange(L-1)]
for i in xrange(S):
# Given i, running_prob[j] means probability of S[i-j:i+1] matching target[:j+1].
expected_bananas += running_prob[L-2] * keyboard_prob[target[L-1]]
# Update the probability in the current index i.
for j in xrange(L-2, 0, -1):
running_prob[j] = running_prob[j-1] * keyboard_prob[target[j]]
running_prob[0] = keyboard_prob[target[0]]
return ideal_bananas - expected_bananas
for case in xrange(input()):
K, L, S = map(int, raw_input().strip().split())
keyboard = raw_input()
target = raw_input()
print "Case #%d: %.10f" % (case+1, remaining_bananas(K, L, S, keyboard, target))