# Program to count number of similar substrings for each query in Python

Suppose we have two strings s and a set of query Q. Where Q[i] contains pair (l, r), for each substring of s from l to r, we have to find number of substrings s from x to y where they are similar. Two strings s and t are similar if they follow these rules −

• They are of same length

• For each pair of indices (i, j), if s[i] is same as s[j], then it must satisfy t[i] = t[j], and similarly if s[i] is not same as s[j], then t[i] and t[j] must be different.

So, if the input is like s = "hjhhbcbk" Q = [(1,2), (2,4)], then the output will be [6, 1] because

• For first query the similar substrings are "hj", "jh", "hb", "bc", "cb" and "bk".
• For first query the similar substring is "jhh"

To solve this, we will follow these steps −

• fp := a new list
• Define a function calc_fingerprint() . This will take s
• dict := a new dictionary, and initially insert key-value pair (s[0], 0)
• fp := "0"
• j := 1
• for i in range 1 to size of s - 1, do
• if s[i] is not present in dict, then
• dict[s[i]] := j
• j = j+1
• fp := fp + string representation of dict[s[i]]
• return integer form of fp
• From the main method, do the following −
• if size of s > 10, then
• for i in range 0 to size of s - 10, do
• x := calc_fingerprint(s[from index i to i+9])
• insert x at the end of fp
• ret := a new list
• for i in range 0 to size of Q - 1, do
• (a, b) := Q[i]
• s1 := substring of s from index a-1 to b-1
• k := 0
• for i in range 0 to size of s - (b-a), do
• if b-a > 9 and fp[a-1] is not same as fp[i], then
• go for next iteration
• dict := a new empty map
• s2 := substring of s from index i to i+(b-a)
• for i in range 0 to b-a, do
• if s2[i] is not in dict, then
• if s1[i] is in values of dict, then
• come out from loop
• dict[s2[i]] := s1[i]
• if dict[s2[i]] is not same as s1[i], then
• come out from loop
• otherwise,
• k := k + 1
• insert k at the end of ret
• return ret

## Example

Let us see the following implementation to get better understanding −

fp = []

def calc_fingerprint(s):
dict = {s[0]: 0}
fp = "0"
j = 1
for i in range(1, len(s)):
if s[i] not in dict:
dict[s[i]], j = j, j+1
fp += str(dict[s[i]])
return int(fp)

def solve(s, Q):
if len(s) > 10:
for i in range(0, len(s)-10):
fp.append(calc_fingerprint(s[i: i+10]))

ret = []
for i in range(len(Q)):
a, b = Q[i]
s1 = s[a-1:b]
k = 0
for i in range(len(s)-(b-a)):
if b-a > 9 and fp[a-1] != fp[i]:
continue
dict = {}
s2 = s[i:i+(b-a)+1]
for i in range(b-a+1):
if s2[i] not in dict:
if s1[i] in dict.values(): break
dict[s2[i]] = s1[i]
if dict[s2[i]] != s1[i]: break
else:
k += 1
ret.append(k)

return ret

s = "hjhhbcbk"
Q = [(1,2), (2,4)]
print(solve(s, Q))

## Input

"hjhhbcbk", [(1,2), (2,4)]


## Output

[6, 1]

Updated on: 11-Oct-2021

192 Views