Buggy python submission (verdict: Time Limit Exceeded):
#!/mnt/c/Users/moiki/bash/env/bin/python
# N,M = map(int, input().split())
S = input()
from collections import defaultdict
from bisect import bisect_left
a = []
b = []
c = []
q = []

for e,s in enumerate(S):
    if s == "A" :
        a.append(e)
    if s == "B" :
        b.append(e)
    if s == "C" :
        c.append(e)
    if s == "?":
        q.append(e)

ans = 0
MOD = int(1e9+7)

for ea in a:
    for ib in range( bisect_left(b, ea+1), len(b)):
        eb = b[ib]
        if len(q) >= 0:
            ans += (len(c) - bisect_left(c, eb+1)  ) * pow(3, len(q), MOD)

        # use q in c 
        if len(q) >= 1:
            ans += (len(q) - bisect_left(q, eb+1)  ) * pow(3,len(q)-1, MOD)

    # use q in b
    for iq in range(bisect_left(q, ea+1), len(q)):
        eq = q[iq]
        if len(q) >= 1:
            ans += (len(c) - bisect_left(c, eq+1) ) * pow(3, len(q)-1, MOD) 

        # use q in b, c
        if len(q) >= 2:
            ans += (len(q) - bisect_left(q, eq+1) ) * pow(3, len(q)-2, MOD)
        # (len(q) - bisect_left(c, eq+1) ) ** pow(3, len(q)-1, MOD) 

    ans %= MOD
for eaq in q:
    for ib in range( bisect_left(b, eaq+1), len(b)):
        eb = b[ib]
        if len(q) >= 1:
            ans += (len(c) - bisect_left(c, eb+1)  ) * pow(3, len(q)-1, MOD)

        # use q in c 
        if len(q) >= 2:
            ans += (len(q) - bisect_left(q, eb+1)  ) * pow(3,len(q)-2, MOD)

    # use q in b
    for iq in range(bisect_left(q, eaq+1), len(q)):
        eq = q[iq]
        if len(q) >= 2:
            ans += (len(c) - bisect_left(c, eq+1) ) * pow(3, len(q)-2, MOD) 

        # use q in b, c
        if len(q) >= 3:
            ans += (len(q) - bisect_left(q, eq+1) ) * pow(3, len(q)-3, MOD)

    ans %= MOD
print(ans % MOD)
    


Fixed submission:
#!/mnt/c/Users/moiki/bash/env/bin/python
# N,M = map(int, input().split())
S = input()
from collections import defaultdict
from bisect import bisect_left, bisect_right
a = []
b = []
c = []
# a = defaultdict(list)
# b = defaultdict(list)
# c = defaultdict(list)
q = []

for e,s in enumerate(S):
    if s == "A" :
        a.append(e)
    if s == "B" :
        b.append(e)
    if s == "C" :
        c.append(e)
    if s == "?":
        q.append(e)

ans = 0
MOD = int(1e9+7)

for eb in b:
    range_a = bisect_right(a, eb-1)
    # print("eb: {eb}, bisect_right({a}, {eb1}): {bis}".format
            # (eb = eb, a=a, eb1=eb-1, bis=bisect_right(a,eb-1)))
    range_c = len(c) - bisect_left(c, eb+1)
    
    range_cq = len(q) - bisect_left(q, eb+1)
    range_aq = bisect_right(q, eb-1)

    ans += range_a*range_c * pow(3, len(q), MOD) % MOD
    ans %= MOD
    if len(q)>=1:
        ans += range_a*range_cq * pow(3, len(q)-1, MOD)
        ans += range_aq*range_c * pow(3, len(q)-1, MOD)
        ans %= MOD
    if len(q)>=2:
        ans += range_aq*range_cq * pow(3, len(q)-2, MOD)
        ans %= MOD
for eq in q:
    # print("eb: {eb}, bisect_right({a}, {eb1}): {bis}".format
            # (eb = eq, a=a, eb1=eq-1, bis=bisect_right(a,eq-1)))
    range_a = bisect_right(a, eq-1)
    range_c = len(c) - bisect_left(c, eq+1)
    range_cq = len(q) - bisect_left(q, eq+1)
    range_aq = bisect_right(q, eq-1)

    ans += range_a*range_c * pow(3, len(q)-1, MOD)
    ans %= MOD
    if len(q) >= 2:
        ans += range_a*range_cq * pow(3, len(q)-2, MOD)
        ans += range_aq*range_c * pow(3, len(q)-2, MOD)
        ans %= MOD
    if len(q) >= 3:
        ans += range_aq*range_cq * pow(3, len(q)-3, MOD)
        ans %= MOD
    
print(ans % MOD)

Buggy python submission (verdict: Time Limit Exceeded):
#!/mnt/c/Users/moiki/bash/env/bin/python
# N,M = map(int, input().split())
S = input()
from collections import defaultdict
from bisect import bisect_left
a = []
b = []
c = []
# a = defaultdict(list)
# b = defaultdict(list)
# c = defaultdict(list)
q = []

for e,s in enumerate(S):
    if s == "A" :
        a.append(e)
    if s == "B" :
        b.append(e)
    if s == "C" :
        c.append(e)
    if s == "?":
        a.append(e)
        b.append(e)
        c.append(e)
        q.append(e)

ans = 0
MOD = int(1e9+7)
for ea in a:
    # print("ea: ", ea, a)
    for ib in range( bisect_left(b, ea+1), len(b)):
        eb = b[ib]
        # print("\teb: ", eb, b)
        # print("\t\tec: ", bisect_left(c, eb+1), "c: ", c, "ans += ", len(c) - bisect_left(c,eb+1) )
        for ic in range(bisect_left(c, eb+1), len(c)):
            ec = c[ic]
            qcnt = len(q) - (1 if ea in q else 0) - (1 if eb in q else 0) - (1 if ec in q else 0)
            ans += pow(3, qcnt, MOD) 

        ans %= MOD
        # ans += len(c) - bisect_left(c, eb+1)  
        # ans += (len(c) - bisect_left(c, eb+1)  ) ** pow(3, 
print(ans % MOD)
    


Fixed submission:
#!/mnt/c/Users/moiki/bash/env/bin/python
# N,M = map(int, input().split())
S = input()
from collections import defaultdict
from bisect import bisect_left, bisect_right
a = []
b = []
c = []
# a = defaultdict(list)
# b = defaultdict(list)
# c = defaultdict(list)
q = []

for e,s in enumerate(S):
    if s == "A" :
        a.append(e)
    if s == "B" :
        b.append(e)
    if s == "C" :
        c.append(e)
    if s == "?":
        q.append(e)

ans = 0
MOD = int(1e9+7)

for eb in b:
    range_a = bisect_right(a, eb-1)
    # print("eb: {eb}, bisect_right({a}, {eb1}): {bis}".format
            # (eb = eb, a=a, eb1=eb-1, bis=bisect_right(a,eb-1)))
    range_c = len(c) - bisect_left(c, eb+1)
    
    range_cq = len(q) - bisect_left(q, eb+1)
    range_aq = bisect_right(q, eb-1)

    ans += range_a*range_c * pow(3, len(q), MOD) % MOD
    ans %= MOD
    if len(q)>=1:
        ans += range_a*range_cq * pow(3, len(q)-1, MOD)
        ans += range_aq*range_c * pow(3, len(q)-1, MOD)
        ans %= MOD
    if len(q)>=2:
        ans += range_aq*range_cq * pow(3, len(q)-2, MOD)
        ans %= MOD
for eq in q:
    # print("eb: {eb}, bisect_right({a}, {eb1}): {bis}".format
            # (eb = eq, a=a, eb1=eq-1, bis=bisect_right(a,eq-1)))
    range_a = bisect_right(a, eq-1)
    range_c = len(c) - bisect_left(c, eq+1)
    range_cq = len(q) - bisect_left(q, eq+1)
    range_aq = bisect_right(q, eq-1)

    ans += range_a*range_c * pow(3, len(q)-1, MOD)
    ans %= MOD
    if len(q) >= 2:
        ans += range_a*range_cq * pow(3, len(q)-2, MOD)
        ans += range_aq*range_c * pow(3, len(q)-2, MOD)
        ans %= MOD
    if len(q) >= 3:
        ans += range_aq*range_cq * pow(3, len(q)-3, MOD)
        ans %= MOD
    
print(ans % MOD)