Buggy python submission (verdict: Time Limit Exceeded):
# D - We Love ABC

S = input()
N = len(S)
MOD = 10**9 + 7

def find_cumsum(X):
    output = [1] if S[0] == X else [0]    
    for idx in range(1,N):
        if S[idx] == X:
            output.append(output[-1]+1)
        else:
            output.append(output[-1])
    return output

q_count = S.count("?")
A_cumsum = find_cumsum("A")
q_cumsum = find_cumsum("?")
        
# last_b[i][j] : S[j]を末尾の"B"とするABのインデックスのパターンの中で、i個の?を"AB"のために使用したもの
last_b = [[0] for _ in range(3)]
for idx in range(1,N):
    if S[idx] == "B":
        last_b[0].append(A_cumsum[idx-1]) # AB
        last_b[1].append(q_cumsum[idx-1]) # ?B
        last_b[2].append(0)
    elif S[idx] == "?":
        last_b[0].append(0)
        last_b[1].append(A_cumsum[idx-1]) # A?
        last_b[2].append(q_cumsum[idx-1]) # ??
    else:
        for i in [0,1,2]:
            last_b[i].append(0)

last_b_cumsum = [[last_b[0][0]], [last_b[1][0]], [last_b[2][0]]]
for i in range(3):
    for idx in range(1,N):
        last_b_cumsum[i].append((last_b[i][idx] + last_b_cumsum[i][-1]) % MOD)

ans = 0
for idx in range(2,N):
    ans %= MOD
    if S[idx] == "C":
        for n_q in range(min(q_count,2)+1):
            ans += last_b_cumsum[n_q][idx-1] * 3**(q_count-n_q)
    elif S[idx] == "?":
        for n_q in range(1, min(q_count,3)+1):
            ans += last_b_cumsum[n_q-1][idx-1] * 3**(q_count-n_q)
        
print(ans % MOD)

Fixed submission:
# D - We Love ABC

S = list(input())
MOD = 10**9 + 7

n_possible = 1 # その場所以前の文字列としてあり得るパターン
A = 0 # その場所以前の文字列におけるA数
B = 0
C = 0

for s in S:
    if s == "A":
        A += n_possible
    elif s == "B":
        B += A
    elif s == "C":
        C += B
    else:
        # X = 3*X + Y
        # この場所の？を (AorABorABCの一部に含めない場合) + (AorABorABCの一部に含める場合)
        C = 3*C + B
        B = 3*B + A
        A = 3*A + n_possible
        n_possible *= 3
    n_possible %= MOD
    A %= MOD
    B %= MOD
    C %= MOD
        
print(C)

Buggy python submission (verdict: Time Limit Exceeded):
# D - We Love ABC

S = input()
N = len(S)
MOD = 10**9 + 7

def find_cumsum(X):
    output = [1] if S[0] == X else [0]    
    for idx in range(1,N):
        if S[idx] == X:
            output.append(output[-1]+1)
        else:
            output.append(output[-1])
    return output

q_count = S.count("?")
A_cumsum = find_cumsum("A")
q_cumsum = find_cumsum("?")
        
# last_b[i][j] : S[j]を末尾の"B"とするABのインデックスのパターンの中で、i個の?を"AB"のために使用したもの
last_b = [[0] for _ in range(3)]
for idx in range(1,N):
    if S[idx] == "B":
        last_b[0].append(A_cumsum[idx-1]) # AB
        last_b[1].append(q_cumsum[idx-1]) # ?B
        last_b[2].append(0)
    elif S[idx] == "?":
        last_b[0].append(0)
        last_b[1].append(A_cumsum[idx-1]) # A?
        last_b[2].append(q_cumsum[idx-1]) # ??
    else:
        for i in [0,1,2]:
            last_b[i].append(0)

last_b_cumsum = [[last_b[0][0]], [last_b[1][0]], [last_b[2][0]]]
for i in range(3):
    for idx in range(1,N):
        last_b_cumsum[i].append((last_b[i][idx] + last_b_cumsum[i][-1]) % MOD)

ans = 0
for idx in range(2,N):
    ans %= MOD
    if S[idx] == "C":
        for n_q in range(min(q_count,2)+1):
            ans += last_b_cumsum[n_q][idx-1] * 3**(q_count-n_q)
    elif S[idx] == "?":
        for n_q in range(1, min(q_count,3)+1):
            ans += last_b_cumsum[n_q-1][idx-1] * 3**(q_count-n_q)
        
print(ans % MOD)

Fixed submission:
# D - We Love ABC

S = list(input())
MOD = 10**9 + 7

n_possible = 1 # その場所以前の文字列としてあり得るパターン
A = 0 # その場所以前の文字列におけるA数
B = 0
C = 0

for s in S:
    if s == "A":
        A += n_possible
    elif s == "B":
        B += A
    elif s == "C":
        C += B
    else:
        # X = 3*X + Y
        # この場所の？を (AorABorABCの一部に含めない場合) + (AorABorABCの一部に含める場合)
        C = 3*C + B
        B = 3*B + A
        A = 3*A + n_possible
        n_possible *= 3
    n_possible %= MOD
    A %= MOD
    B %= MOD
    C %= MOD
        
print(C)

Buggy python submission (verdict: Time Limit Exceeded):
# D - We Love ABC

S = input()
N = len(S)
MOD = 10**9 + 7

def find_cumsum(X):
    output = [1] if S[0] == X else [0]    
    for idx in range(1,N):
        if S[idx] == X:
            output.append(output[-1]+1)
        else:
            output.append(output[-1])
    return output

q_count = S.count("?")
A_cumsum = find_cumsum("A")
q_cumsum = find_cumsum("?")
        
# last_b[i][j] : S[j]を末尾の"B"とするABのインデックスのパターンの中で、i個の?を"AB"のために使用したもの
last_b = [[0] for _ in range(3)]
for idx in range(1,N):
    if S[idx] == "B":
        last_b[0].append(A_cumsum[idx-1]) # AB
        last_b[1].append(q_cumsum[idx-1]) # ?B
        last_b[2].append(0)
    elif S[idx] == "?":
        last_b[0].append(0)
        last_b[1].append(A_cumsum[idx-1]) # A?
        last_b[2].append(q_cumsum[idx-1]) # ??
    else:
        for i in [0,1,2]:
            last_b[i].append(0)

last_b_cumsum = [[last_b[0][0]], [last_b[1][0]], [last_b[2][0]]]
for i in range(3):
    for idx in range(1,N):
        last_b_cumsum[i].append((last_b[i][idx] + last_b_cumsum[i][-1]) % MOD)

# last_c[i] : S[i]を末尾の"C"とするABCのパターン数で、しかも?の置き換えも考慮したもの
last_c = [0]*2
for idx in range(2,N):
    n_ABC = 0
    if S[idx] == "C":
        for n_q in range(min(q_count,2)+1):
            n_ABC += last_b_cumsum[n_q][idx-1] * 3**(q_count-n_q)
    elif S[idx] == "?":
        for n_q in range(1, min(q_count,3)+1):
            n_ABC += last_b_cumsum[n_q-1][idx-1] * 3**(q_count-n_q)
    last_c.append(n_ABC % MOD)
        
print(sum(last_c) % MOD)

Fixed submission:
# D - We Love ABC

S = list(input())
MOD = 10**9 + 7

n_possible = 1 # その場所以前の文字列としてあり得るパターン
A = 0 # その場所以前の文字列におけるA数
B = 0
C = 0

for s in S:
    if s == "A":
        A += n_possible
    elif s == "B":
        B += A
    elif s == "C":
        C += B
    else:
        # X = 3*X + Y
        # この場所の？を (AorABorABCの一部に含めない場合) + (AorABorABCの一部に含める場合)
        C = 3*C + B
        B = 3*B + A
        A = 3*A + n_possible
        n_possible *= 3
    n_possible %= MOD
    A %= MOD
    B %= MOD
    C %= MOD
        
print(C)