Buggy python submission (verdict: Time Limit Exceeded):
#b
import sys
def input(): return sys.stdin.readline().strip()
n = int(input())
s = [input() for _ in range(n)]
s.sort(key=len)
ans = 0
trie = {'!': True}
for si in s:
    cursor = trie
    si = list(si)
    while True:
        for nextchar in cursor:
            if nextchar == '!':
                continue
            if '!' in cursor[nextchar] and nextchar in si:
                ans += 1
        popchar = si.pop(-1)
        if popchar in cursor:
            cursor = cursor[popchar]
        else:
            cursor[popchar] = {}
            cursor = cursor[popchar]
            for popchar in reversed(si):
                cursor[popchar] = {}
                cursor = cursor[popchar]
            cursor['!'] = True
            break
print(ans)

Fixed submission:
#b（直し）
class TrieNode:
    def __init__(self):
        self.parent = None
        self.children = {}
    def new_child(self, key):
        self.children[key] = TrieNode()
        self.children[key].parent = self
        self.children[key].label = key
        return self.children[key]

import sys
def input(): return sys.stdin.readline().strip()

n = int(input())
s = [input() for _ in range(n)]
ans = -n # (Si, Si)
trie = TrieNode()
ends = set()

#build the trie
for si in s:
    cursor = trie
    for char in reversed(si):
        if char in cursor.children:
            cursor = cursor.children[char]
        else:
            cursor = cursor.new_child(char)
    else:
        ends.add(cursor)

#climb up the trie
for cursor in ends:
    head = set()
    while cursor.parent is not None:
        head.add(cursor.label)
        cursor = cursor.parent
        for char in cursor.children:
            if cursor.children[char] in ends and char in head:
                ans += 1
print(ans)

Buggy python submission (verdict: Time Limit Exceeded):
#b
n = int(input())
s = [input() for _ in range(n)]
s.sort(key=len)
ans = 0
trie = {'!': True}
for si in s:
    cursor = trie
    si = list(si)
    while True:
        for nextchar in cursor:
            if nextchar == '!':
                continue
            if '!' in cursor[nextchar] and nextchar in si:
                ans += 1
        popchar = si.pop(-1)
        if popchar in cursor:
            cursor = cursor[popchar]
        else:
            cursor[popchar] = {}
            cursor = cursor[popchar]
            for popchar in reversed(si):
                cursor[popchar] = {}
                cursor = cursor[popchar]
            cursor['!'] = True
            break
print(ans)

Fixed submission:
#b（直し）
class TrieNode:
    def __init__(self):
        self.parent = None
        self.children = {}
    def new_child(self, key):
        self.children[key] = TrieNode()
        self.children[key].parent = self
        self.children[key].label = key
        return self.children[key]

import sys
def input(): return sys.stdin.readline().strip()

n = int(input())
s = [input() for _ in range(n)]
ans = -n # (Si, Si)
trie = TrieNode()
ends = set()

#build the trie
for si in s:
    cursor = trie
    for char in reversed(si):
        if char in cursor.children:
            cursor = cursor.children[char]
        else:
            cursor = cursor.new_child(char)
    else:
        ends.add(cursor)

#climb up the trie
for cursor in ends:
    head = set()
    while cursor.parent is not None:
        head.add(cursor.label)
        cursor = cursor.parent
        for char in cursor.children:
            if cursor.children[char] in ends and char in head:
                ans += 1
print(ans)