Buggy python submission (verdict: Time Limit Exceeded):
from scipy.misc import comb

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


ca = [0] * N
cq1 = [0] * N
if S[0] == 'A':
    ca[0] = 1
if S[0] == '?':
    cq1[0] = 1
for i in range(1, N):
    if S[i] == 'A':
        ca[i] = ca[i - 1] + 1
    else:
        ca[i] = ca[i - 1]
    if S[i] == '?':
        cq1[i] = cq1[i - 1] + 1
    else:
        cq1[i] = cq1[i - 1]

cc = [0] * N
cq2 = [0] * N
if S[-1] == 'C':
    cc[0] = 1
if S[-1] == '?':
    cq2[0] = 1
for i in range(1, N):
    if S[N - 1 - i] == 'C':
        cc[i] = cc[i - 1] + 1
    else:
        cc[i] = cc[i - 1]
    if S[N - 1 - i] == '?':
        cq2[i] = cq2[i - 1] + 1
    else:
        cq2[i] = cq2[i - 1]
cc = cc[::-1]
cq2 = cq2[::-1]

memo = {}
def f(q):
    if q in memo:
        return memo[q]
    x = [0] * (q + 1)
    for i in range(q + 1):
        x[i] = 2 ** (q - i) * comb(q, i, exact=True)
    memo[q] = x
    return x


memo2 = {}
def g(x, q):
    if (x, q) in memo2:
        return memo2[(x, q)]
    t = f(q)
    c = 0
    for i in range(q + 1):
        c += t[i] * (i + x)
    memo2[(x, q)] = c
    return c


ans = 0
for i in range(1, N - 1):
    if S[i] in ['B', '?']:
        ans += g(ca[i - 1], cq1[i - 1]) * g(cc[i + 1], cq2[i + 1])
print(ans % mod)


Fixed submission:
S = input()
N = len(S)
mod = 10 ** 9 + 7

# dp[i][j]: i番目までの文字までで、状態jになる組み合わせ数
dp = [[0 for _ in range(4)] for _ in range(N + 1)]
dp[0][0] = 1

for i in range(N):
    if S[i] in ['A', '?']:
        for j in range(4):
            dp[i + 1][j] += dp[i][j]
        dp[i + 1][1] += dp[i][0]
    if S[i] in ['B', '?']:
        for j in range(4):
            dp[i + 1][j] += dp[i][j]
        dp[i + 1][2] += dp[i][1]
    if S[i] in ['C', '?']:
        for j in range(4):
            dp[i + 1][j] += dp[i][j]
        dp[i + 1][3] += dp[i][2]

    for j in range(4):
        dp[i + 1][j] %= mod

print(dp[N][3])

Buggy python submission (verdict: Time Limit Exceeded):
from scipy.misc import comb

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


ca = [0] * N
cq1 = [0] * N
if S[0] == 'A':
    ca[0] = 1
if S[0] == '?':
    cq1[0] = 1
for i in range(1, N):
    if S[i] == 'A':
        ca[i] = ca[i - 1] + 1
    else:
        ca[i] = ca[i - 1]
    if S[i] == '?':
        cq1[i] = cq1[i - 1] + 1
    else:
        cq1[i] = cq1[i - 1]

cc = [0] * N
cq2 = [0] * N
if S[-1] == 'C':
    cc[0] = 1
if S[-1] == '?':
    cq2[0] = 1
for i in range(1, N):
    if S[N - 1 - i] == 'C':
        cc[i] = cc[i - 1] + 1
    else:
        cc[i] = cc[i - 1]
    if S[N - 1 - i] == '?':
        cq2[i] = cq2[i - 1] + 1
    else:
        cq2[i] = cq2[i - 1]
cc = cc[::-1]
cq2 = cq2[::-1]

memo = {}
def f(q):
    if q in memo:
        return memo[q]
    x = [0] * (q + 1)
    for i in range(q + 1):
        x[i] = 2 ** (q - i) * comb(q, i, exact=True)
    memo[q] = x
    return x


def g(x, q):
    t = f(q)
    c = 0
    for i in range(q + 1):
        c += t[i] * (i + x)
    return c


ans = 0
for i in range(1, N - 1):
    if S[i] in ['B', '?']:
        ans += g(ca[i - 1], cq1[i - 1]) * g(cc[i + 1], cq2[i + 1])
print(ans % mod)


Fixed submission:
S = input()
N = len(S)
mod = 10 ** 9 + 7

# dp[i][j]: i番目までの文字までで、状態jになる組み合わせ数
dp = [[0 for _ in range(4)] for _ in range(N + 1)]
dp[0][0] = 1

for i in range(N):
    if S[i] in ['A', '?']:
        for j in range(4):
            dp[i + 1][j] += dp[i][j]
        dp[i + 1][1] += dp[i][0]
    if S[i] in ['B', '?']:
        for j in range(4):
            dp[i + 1][j] += dp[i][j]
        dp[i + 1][2] += dp[i][1]
    if S[i] in ['C', '?']:
        for j in range(4):
            dp[i + 1][j] += dp[i][j]
        dp[i + 1][3] += dp[i][2]

    for j in range(4):
        dp[i + 1][j] %= mod

print(dp[N][3])