Consider a string, $S$, of $n$ lowercase English letters where each character, $s_i$ ($0\leq i<n)$, denotes the letter at index $\boldsymbol{i}$ in $S$. We define an $(a,b,c,d)$ palindromic tuple of $S$ to be a sequence of indices in $S$ satisfying the following criteria:

$\boldsymbol{s_{a}}=\boldsymbol{s_{d}}$, meaning the characters located at indices $a$ and $d$ are the same.
$s_b=s_c$, meaning the characters located at indices $b$ and $c$ are the same.
$0\leq a\lt b\lt c\lt d\lt|s|$, meaning that $a$, $b$, $c$, and $d$ are ascending in value and are valid indices within string $S$.

Given $S$, find and print the number of $(a,b,c,d)$ tuples satisfying the above conditions. As this value can be quite large, print it modulo $(10^9+7)$.  

Function Description 

Complete the function shortPalindrome in the editor below.  

shortPalindrome has the following paramter(s): 

- string s: a string  

Returns 

- int: the number of tuples, modulo $(10^9+7)$  

Input Format

A single string, $S$. 

Constraints

$1\leq|s|\leq10^6$
It is guaranteed that $S$ only contains lowercase English letters.  

Sample Input 0

kkkkkkz

Sample Output 0

15

Explanation 0

The letter z will not be part of a valid tuple because you need at least two of the same character to satisfy the conditions defined above. Because all tuples consisting of four k's are valid, we just need to find the number of ways that we can choose four of the six k's. This means our answer is $\binom{6}{4}\mod(10^9+7)=15$.

Sample Input 1

ghhggh

Sample Output 1

4

Explanation 1

The valid tuples are:

$(0,1,2,3)$
$(0,1,2,4)$
$(1,3,4,5)$
$(2,3,4,5)$

Thus, our answer is $4\:\:\:\text{mod}\:(10^9+7)=4$.

Sample Input 0

kkkkkkz

Sample Output 0

15

Sample Input 1

abbaab

Sample Output 1

4

Sample Input 2
akakak

Sample Output 2
2

Explanation 2

Tuples possible are $(1,2,4,5)~and~(0,1,3,4)$

Source: hackerrank | Difficulty: MEDIUM
Tags: Complete search


Solutions:
mod = 10 ** 9 + 7

def sum_multi(A, B):
	return A[0] * B[0] + A[1] * B[1] + A[2] * B[2] + A[3] * B[3] + A[4] * B[4] + A[5] * B[5] + A[6] * B[6] + A[7] * B[7] + A[8] * B[8] + A[9] * B[9] + A[10] * B[10] + A[11] * B[11] + A[12] * B[12] + A[13] * B[13] + A[14] * B[14] + A[15] * B[15] + A[16] * B[16] + A[17] * B[17] + A[18] * B[18] + A[19] * B[19] + A[20] * B[20] + A[21] * B[21] + A[22] * B[22] + A[23] * B[23] + A[24] * B[24] + A[25] * B[25]

def left_vector_add(A, B):
	A[0] += B[0]
	A[1] += B[1]
	A[2] += B[2]
	A[3] += B[3]
	A[4] += B[4]
	A[5] += B[5]
	A[6] += B[6]
	A[7] += B[7]
	A[8] += B[8]
	A[9] += B[9]
	A[10] += B[10]
	A[11] += B[11]
	A[12] += B[12]
	A[13] += B[13]
	A[14] += B[14]
	A[15] += B[15]
	A[16] += B[16]
	A[17] += B[17]
	A[18] += B[18]
	A[19] += B[19]
	A[20] += B[20]
	A[21] += B[21]
	A[22] += B[22]
	A[23] += B[23]
	A[24] += B[24]
	A[25] += B[25]

def left_vector_minus(A, B):
	A[0] -= B[0]
	A[1] -= B[1]
	A[2] -= B[2]
	A[3] -= B[3]
	A[4] -= B[4]
	A[5] -= B[5]
	A[6] -= B[6]
	A[7] -= B[7]
	A[8] -= B[8]
	A[9] -= B[9]
	A[10] -= B[10]
	A[11] -= B[11]
	A[12] -= B[12]
	A[13] -= B[13]
	A[14] -= B[14]
	A[15] -= B[15]
	A[16] -= B[16]
	A[17] -= B[17]
	A[18] -= B[18]
	A[19] -= B[19]
	A[20] -= B[20]
	A[21] -= B[21]
	A[22] -= B[22]
	A[23] -= B[23]
	A[24] -= B[24]
	A[25] -= B[25]
s = [ord(c) - 97 for c in input().strip()]
post = [[0 for _ in range(26)] for _ in range(26)]
working = [0 for _ in range(26)]
working[s[len(s) - 1]] = 1
for i in range(len(s) - 2, 0, -1):
	c = s[i]
	left_vector_add(post[c], working)
	working[c] += 1
total = 0
forward = [0 for _ in range(26)]
forward[s[0]] = 1
for i in range(1, len(s) - 2):
	b = s[i]
	working[b] -= 1
	left_vector_minus(post[b], working)
	total = (total + sum_multi(forward, post[b])) % mod
	forward[b] += 1
print(total)


from collections import defaultdict
import string

def count_pal(input_string):
	m = dict(zip(string.ascii_lowercase, range(26)))
	data = [m[c] for c in input_string]
	singles = [0] * 26
	doubles = [[0] * 26 for i in range(26)]
	triples = [0] * 26
	total = 0
	for current in data:
		total += triples[current]
		for c in range(26):
			triples[c] += doubles[c][current]
		for c in range(26):
			doubles[c][current] += singles[c]
		singles[current] += 1
	return total
s = input()
print(count_pal(s) % (10 ** 9 + 7))


def count_short_palindromes(input_string):
	alphabet_to_number = {'abcdefghijklmnopqrstuvwxyz'[i]: i for i in range(26)}
	individual_freq = [0 for i in range(26)]
	remaining_letter_left = [0 for i in range(26)]
	pair_freq = [0 for i in range(26 * 26)]
	short_palindromes_count = 0
	for ch in input_string:
		v = alphabet_to_number[ch]
		short_palindromes_count += remaining_letter_left[v]
		for i in range(26):
			remaining_letter_left[i] += pair_freq[i * 26 + v]
		for i in range(26):
			pair_freq[i * 26 + v] += individual_freq[i]
		individual_freq[v] += 1
	return short_palindromes_count
input_string = input().strip()
print(count_short_palindromes(input_string) % (10 ** 9 + 7))


from collections import defaultdict as di
data = [x for x in input().strip()]
chara = set(data)
summa = 0
for c in chara:
	a = 0
	b = di(int)
	doublepairs = 0
	for d in data:
		if d == c:
			summa += doublepairs
			doublepairs += b[c]
			b[c] += a
			a += 1
		else:
			doublepairs += b[d]
			b[d] += a
print(summa % (10 ** 9 + 7))


from collections import defaultdict
import string

def count_pal(input_string):
	m = dict(zip(string.ascii_lowercase, range(26)))
	data = [m[c] for c in input_string]
	singles = [0] * 26
	doubles = [[0] * 26 for i in range(26)]
	triples = [0] * 26
	total = 0
	for current in data:
		total += triples[current]
		for c in range(26):
			triples[c] += doubles[c][current]
		for c in range(26):
			doubles[c][current] += singles[c]
		singles[current] += 1
	return total
s = input()
print(count_pal(s) % (10 ** 9 + 7))


from collections import defaultdict
import string

def count_pal(input_string):
	m = dict(zip(string.ascii_lowercase, range(26)))
	data = [m[c] for c in input_string]
	singles = [0] * 26
	doubles = [[0] * 26 for i in range(26)]
	triples = [0] * 26
	total = 0
	for current in data:
		total += triples[current]
		for c in range(26):
			triples[c] += doubles[c][current]
		for c in range(26):
			doubles[c][current] += singles[c]
		singles[current] += 1
	return total
s = input()
print(count_pal(s) % (10 ** 9 + 7))


from collections import defaultdict
import string

def count_pal(input_string):
	m = dict(zip(string.ascii_lowercase, range(26)))
	data = [m[c] for c in input_string]
	singles = [0] * 26
	doubles = [[0] * 26 for i in range(26)]
	triples = [0] * 26
	total = 0
	for current in data:
		total += triples[current]
		for c in range(26):
			triples[c] += doubles[c][current]
		for c in range(26):
			doubles[c][current] += singles[c]
		singles[current] += 1
	return total
s = input()
print(count_pal(s) % (10 ** 9 + 7))


mod = 10 ** 9 + 7

def shortPalindrome(s):
	res = 0
	dim1 = [0] * 26
	dim2 = [[0] * 26 for _ in range(26)]
	dim3 = [0] * 26
	for c in s:
		idx = ord(c) - ord('a')
		res += dim3[idx]
		res %= mod
		for i in range(26):
			dim3[i] += dim2[i][idx]
		for j in range(26):
			dim2[j][idx] += dim1[j]
		dim1[idx] += 1
	return res % mod
s = input()
print(shortPalindrome(s))


from collections import defaultdict
import string

def count_pal(input_string):
	m = dict(zip(string.ascii_lowercase, range(26)))
	data = [m[c] for c in input_string]
	singles = [0] * 26
	doubles = [[0] * 26 for i in range(26)]
	triples = [0] * 26
	total = 0
	for current in data:
		total += triples[current]
		for c in range(26):
			triples[c] += doubles[c][current]
		for c in range(26):
			doubles[c][current] += singles[c]
		singles[current] += 1
	return total
s = input()
print(count_pal(s) % (10 ** 9 + 7))


import math
import os
import random
import re
import sys

def shortPalindrome(s):
	md = 10 ** 9 + 7
	one = [0] * 26
	two = [[0] * 26 for _ in range(26)]
	three = [0] * 26
	res = 0
	for c in s:
		c = ord(c) - 97
		res = (res + three[c]) % md
		twoc = two[c]
		for i in range(26):
			three[i] = (three[i] + twoc[i]) % md
		for i in range(26):
			twoc[i] = (twoc[i] + one[i]) % md
		one[c] += 1
	return res
print(shortPalindrome(input()))


def count_short_palindromes(input_string):
	alphabet_to_number = {'abcdefghijklmnopqrstuvwxyz'[i]: i for i in range(26)}
	individual_freq = [0 for i in range(26)]
	remaining_letter_left = [0 for i in range(26)]
	pair_freq = [0 for i in range(26 * 26)]
	short_palindromes_count = 0
	for ch in input_string:
		v = alphabet_to_number[ch]
		short_palindromes_count += remaining_letter_left[v]
		for i in range(26):
			remaining_letter_left[i] += pair_freq[i * 26 + v]
		for i in range(26):
			pair_freq[i * 26 + v] += individual_freq[i]
		individual_freq[v] += 1
	return short_palindromes_count
input_string = input().strip()
print(count_short_palindromes(input_string) % (10 ** 9 + 7))


mod = 10 ** 9 + 7

def sum_multi(A, B):
	return A[0] * B[0] + A[1] * B[1] + A[2] * B[2] + A[3] * B[3] + A[4] * B[4] + A[5] * B[5] + A[6] * B[6] + A[7] * B[7] + A[8] * B[8] + A[9] * B[9] + A[10] * B[10] + A[11] * B[11] + A[12] * B[12] + A[13] * B[13] + A[14] * B[14] + A[15] * B[15] + A[16] * B[16] + A[17] * B[17] + A[18] * B[18] + A[19] * B[19] + A[20] * B[20] + A[21] * B[21] + A[22] * B[22] + A[23] * B[23] + A[24] * B[24] + A[25] * B[25]

def left_vector_add(A, B):
	A[0] += B[0]
	A[1] += B[1]
	A[2] += B[2]
	A[3] += B[3]
	A[4] += B[4]
	A[5] += B[5]
	A[6] += B[6]
	A[7] += B[7]
	A[8] += B[8]
	A[9] += B[9]
	A[10] += B[10]
	A[11] += B[11]
	A[12] += B[12]
	A[13] += B[13]
	A[14] += B[14]
	A[15] += B[15]
	A[16] += B[16]
	A[17] += B[17]
	A[18] += B[18]
	A[19] += B[19]
	A[20] += B[20]
	A[21] += B[21]
	A[22] += B[22]
	A[23] += B[23]
	A[24] += B[24]
	A[25] += B[25]

def left_vector_minus(A, B):
	A[0] -= B[0]
	A[1] -= B[1]
	A[2] -= B[2]
	A[3] -= B[3]
	A[4] -= B[4]
	A[5] -= B[5]
	A[6] -= B[6]
	A[7] -= B[7]
	A[8] -= B[8]
	A[9] -= B[9]
	A[10] -= B[10]
	A[11] -= B[11]
	A[12] -= B[12]
	A[13] -= B[13]
	A[14] -= B[14]
	A[15] -= B[15]
	A[16] -= B[16]
	A[17] -= B[17]
	A[18] -= B[18]
	A[19] -= B[19]
	A[20] -= B[20]
	A[21] -= B[21]
	A[22] -= B[22]
	A[23] -= B[23]
	A[24] -= B[24]
	A[25] -= B[25]
s = [ord(c) - 97 for c in input().strip()]
post = [[0 for _ in range(26)] for _ in range(26)]
working = [0 for _ in range(26)]
working[s[len(s) - 1]] = 1
for i in range(len(s) - 2, 0, -1):
	c = s[i]
	left_vector_add(post[c], working)
	working[c] += 1
total = 0
forward = [0 for _ in range(26)]
forward[s[0]] = 1
for i in range(1, len(s) - 2):
	b = s[i]
	working[b] -= 1
	left_vector_minus(post[b], working)
	total = (total + sum_multi(forward, post[b])) % mod
	forward[b] += 1
print(total)


import math
import os
import random
import re
import sys

def ncr(n, k):
	if n < k:
		return 0
	return math.factorial(n) // (math.factorial(k) * math.factorial(n - k))

def sm(x):
	if x <= 0:
		return 0
	return x * (x + 1) // 2

def shortPalindrome(s):
	alf = 'qazwsxedcrfvtgbyhnujmiklop'
	l1 = {}
	l2 = {}
	l3 = {}
	ans = 0
	l = {}
	for i in alf:
		l3[i] = 0
		l1[i] = 0
		l2[i] = {}
		l[i] = 0
		for k in alf:
			l2[i][k] = 0
	for i in s:
		ans += l3[i] % (10 ** 9 + 7)
		for k in l1:
			l3[k] += l2[i][k]
			l2[i][k] += l1[k]
		l[i] += 1
		l1[i] = l[i]
	return ans
s = input()
result = shortPalindrome(s)
print(result % (10 ** 9 + 7))


from collections import defaultdict
import string

def count_pal(input_string):
	m = dict(zip(string.ascii_lowercase, range(26)))
	data = [m[c] for c in input_string]
	singles = [0] * 26
	doubles = [[0] * 26 for i in range(26)]
	triples = [0] * 26
	total = 0
	for current in data:
		total += triples[current]
		for c in range(26):
			triples[c] += doubles[c][current]
		for c in range(26):
			doubles[c][current] += singles[c]
		singles[current] += 1
	return total
s = input()
print(count_pal(s) % (10 ** 9 + 7))


from collections import defaultdict as di
data = [x for x in input().strip()]
chara = set(data)
summa = 0
for c in chara:
	a = 0
	b = di(int)
	doublepairs = 0
	for d in data:
		if d == c:
			summa += doublepairs
			doublepairs += b[c]
			b[c] += a
			a += 1
		else:
			doublepairs += b[d]
			b[d] += a
print(summa % (10 ** 9 + 7))


from collections import defaultdict
import string

def count_pal(input_string):
	m = dict(zip(string.ascii_lowercase, range(26)))
	data = [m[c] for c in input_string]
	singles = [0] * 26
	doubles = [[0] * 26 for i in range(26)]
	triples = [0] * 26
	total = 0
	for current in data:
		total += triples[current]
		for c in range(26):
			triples[c] += doubles[c][current]
		for c in range(26):
			doubles[c][current] += singles[c]
		singles[current] += 1
	return total
s = input()
print(count_pal(s) % (10 ** 9 + 7))


def shortPalindrome(s):
	mod = 10 ** 9 + 7
	C1 = [0] * 26
	C2 = [0] * 26 * 26
	C3 = [0] * 26 * 26
	count = 0
	r26 = list(range(26))
	for c in s:
		k = ord(c) - 97
		p = 26 * k - 1
		q = k - 26
		for i in r26:
			q += 26
			p += 1
			count += C3[q]
			C3[p] += C2[p]
			C2[p] += C1[i]
		C1[k] += 1
	return count % mod
s = input()
print(shortPalindrome(s) % (10 ** 9 + 7))


from string import ascii_lowercase
A = 26
MOD = 1000000007

def shortPalindrome(s):
	d = {c: i for (i, c) in enumerate(ascii_lowercase)}
	c1 = [0] * A
	c2 = [[0] * A for _ in range(A)]
	c3 = [0] * A
	res = 0
	for c in s:
		i = d[c]
		res += c3[i]
		for j in range(A):
			c3[j] += c2[j][i]
		for j in range(A):
			c2[j][i] += c1[j]
		c1[i] += 1
	return res
print(shortPalindrome(input()) % MOD)


def so(s):
	mod = 10 ** 9 + 7
	C1 = [0] * 26
	C2 = [0] * 676
	C3 = [0] * 676
	count = 0
	r26 = list(range(26))
	for c in s:
		k = ord(c) - 97
		p = 26 * k - 1
		q = k - 26
		for i in r26:
			q += 26
			p += 1
			count += C3[q]
			C3[p] += C2[p]
			C2[p] += C1[i]
		C1[k] += 1
	return count % mod
a = input()
print(so(a))


def shortPalindrome(s):
	mod = 10 ** 9 + 7
	C1 = [0] * 26
	C2 = [0] * 26 * 26
	C3 = [0] * 26 * 26
	count = 0
	r26 = list(range(26))
	for c in s:
		k = ord(c) - 97
		p = 26 * k - 1
		q = k - 26
		for i in r26:
			q += 26
			p += 1
			count += C3[q]
			C3[p] += C2[p]
			C2[p] += C1[i]
		C1[k] += 1
	return count % mod
print(shortPalindrome(list(input(''))))