# 家に帰ったら整理して
# MOD = (10**9) + 7
=begin

# X Y Z K
# A1...AX
# B1...
# C1...

X, Y, Z, K = gets.split.map(&:to_i)
A = gets.split.map(&:to_i).sort.reverse
B = gets.split.map(&:to_i).sort.reverse
C = gets.split.map(&:to_i).sort.reverse
V = Array.new

A.each_with_index do |a, i|
  B.each_with_index do |b, j|
    break if (i + 1) * (j + 1) > K

    C.each_with_index do |c, k|
      break if (i + 1) * (j + 1) * (k + 1) > K

      V << (a + b + c)
    end
  end
end

puts V.sort.reverse[0...K]
=end

# X, Y = gets.split.map(&:to_i)
# ans = 0
# num = X
# while num <= Y
#   ans += 1
#   num *= 2
# end

# p ans

=begin

N = gets.to_i

# u -> v , weight = w
# u v w
temp = []
glaph = Array.new(N) { Hash.new }
(N - 1).times do
  u, v, w = gets.split.map(&:to_i)
  glaph[u - 1][v - 1] = w
  glaph[v - 1][u - 1] = w
end

gone = Array.new(N) { true }
ans = Array.new(N)
queue = [0]

ans[0] = true
gone[0] = true

while curr = queue.shift
  glaph[curr].each do |k, v|
    if gone[k]
      gone[k] = false
      ans[k] = (v%2 == 0) ? ans[curr] : !ans[curr]
      queue << k
    end
  end
end

ans.each { |a| puts a ? '1' : '0' }

=end

# abc121D
# input
# A B
# 123 456
# output
# 435
# A..BのXOR

# a, b = gets.split.map(&:to_i)
# ans = 0
# if a%2 == 1
#   ans = ans ^ a
#   a += 1
# end
# if b%2 == 0
#   ans = ans ^ b
#   b -= 1
# end
# ans = ans ^ (((b - a + 1)/2)%2)
# p ans

# abc120D
# input
# N M
# A1 B1
# ...
# AM BM
# 6 5
# 2 3
# 1 2
# 5 6
# 3 4
# 4 5
# output
# 8
# 9
# 12
# 14
# 15

# class UnionFindWithSize
#   def initialize(size)
#     @rank = Array.new(size) { 0 }
#     @parent = Array.new(size) { |id| id }
#     @union_size = Array.new(size) { 1 }
#   end

#   def unite(id_x, id_y)
#     x_parent = get_parent(id_x)
#     y_parent = get_parent(id_y)
#     return if x_parent == y_parent

#     ary = [@union_size[x_parent], @union_size[y_parent]]
#     if @rank[x_parent] > @rank[y_parent]
#       @parent[y_parent] = x_parent
#       @union_size[x_parent] += ary[1]
#     else
#       @parent[x_parent] = y_parent
#       @union_size[y_parent] += ary[0]
#       @rank[y_parent] += 1 if @rank[x_parent] == @rank[y_parent]
#     end
#     ary
#   end

#   def get_parent(id_x)
#     @parent[id_x] == id_x ? id_x : (@parent[id_x] = get_parent(@parent[id_x]))
#   end
# end

# n, m = gets.split.map(&:to_i)
# bridges = Array.new(m) { Array.new(2) }
# uf = UnionFindWithSize.new(n)
# m.times do |i|
#   bridges[i] = gets.split.map {|j| j.to_i - 1 }
# end
# ans = []
# curr_value = n * (n-1) / 2
# ans << curr_value
# bridges[1..-1].reverse_each do |u, v|
#   if diff = uf.unite(u, v)
#     curr_value -= diff[0] * diff[1]
#   end
#   ans << curr_value
# end

# puts ans.reverse


# https://atcoder.jp/contests/abc119/tasks/abc119_d
# A B Q
# s1
# :
# sA
# t1
# :
# tB
# x1
# :
# xQ

# A,Bをsort AlogA + BlogB (A,B < 10**5)
# xに対して、Aから前後1ずつ、Bから前後1つずつ取り出す(bsearch_indexで当該indexを探す), logA + logB
# A前 + B前, A前 + B後, A後 + B前, A後 + B後 の4つの内どれかが答え
# max(A前,B前,x) - min(A前,B前,x) が1つの値
# ------a1-------a2----x----a3-----a4------
# ----------b1-----b2--x--------b3------b4-

# 350
# 1400
# 301
# 399

# A, B, Q = gets.split.map(&:to_i)
# s = []
# t = []
# A.times do
#   s << gets.chomp.to_i
# end
# B.times do
#   t << gets.chomp.to_i
# end
# s.sort!
# t.sort!

# x = 0
# temp_index = 0
# Q.times do
#   x = gets.chomp.to_i
#   # 各近傍値を取る
#   tmp = s.bsearch_index { |v| v >= x }
#   sl, su = tmp ? (tmp == 0 ? [nil, s[0]] : [s[tmp-1], s[tmp]]) : [s[A - 1], nil]
#   tmp = t.bsearch_index { |v| v >= x }
#   tl, tu = tmp ? (tmp == 0 ? [nil, t[0]] : [t[tmp-1], t[tmp]]) : [t[B - 1], nil]
#   m = 2 * (10 ** 10) + 1
#   if sl
#     if tl
#       m = [[x - sl, x - tl].max, m].min
#     end
#     if tu
#       m = [(tu - sl) + [x - sl, tu - x].min, m].min
#     end
#   end
#   if su
#     if tl
#       m = [(su - tl) + [su-x, x-tl].min , m].min
#     end
#     if tu
#       m = [[su-x, tu-x].max, m].min
#     end
#   end
#   puts m
# end

# https://atcoder.jp/contests/abc119/tasks/abc119_c
# N, *ABC = gets.split.map(&:to_i)
# l = []
# N.times do
#   l << gets.to_i
# end

# cost = 10 ** 9
# [0, 1, 2, 3].repeated_permutation(N).each do |arys|
#   next if [0, 1, 2].any? { |i| !arys.include?(i) }
#   temp_cost = 0
#   length = [0, 0, 0] # a,b,c
#   mp = 0

#   N.times do |i|
#     if arys[i] != 3
#       length[arys[i]] += l[i]
#       mp += 10
#     end
#   end

#   temp_cost = mp
#   3.times do |i|
#     temp_cost += (length[i] - ABC[i]).abs
#   end

#   cost = cost > temp_cost ? temp_cost : cost
# end

# p cost - 30

# https://atcoder.jp/contests/abc122/tasks/abc122_c
# 8 3
# ACACTACG
# 3 7
# 2 3
# 1 8

# N, Q = gets.split.map(&:to_i)
# str = gets.chomp
# # 0文字目まで、1文字目までは自明に0
# rui = [0, 0]
# ite = 2
# str.chars.each_cons(2) do |c1, c2|
#   rui[ite] = rui[ite - 1] + ((c1 == 'A' && c2 == 'C') ? 1 : 0)
#   ite += 1
# end
# Q.times do
#   s, l = gets.split.map(&:to_i)
#   puts rui[l] - rui[s]
# end

# https://atcoder.jp/contests/abc104/tasks/abc104_d
# in
# ????C?????B??????A???????
# out
# 979596887
# in
# ABCBC
# 3

MOD = (10**9) + 7
str = gets.chomp
# n文字目までの'a'の組み合わせの数
dp_a = [0]
# n文字目までの'ab'の組み合わせの数
dp_ab = [0]
# n文字目までの'abc'の組み合わせの数
dp_abc = [0]

dp_none = [1]

a = 'A'
b = 'B'
c = 'C'
str.chars.each.with_index(1) do |s, n|
  case s
  when a
    dp_none[n] = dp_none[n-1]
    dp_a[n] = (dp_a[n-1] + dp_none[n-1])%MOD
    dp_ab[n] = dp_ab[n-1]
    dp_abc[n] = dp_abc[n-1]
  when b
    dp_none[n] = dp_none[n-1]
    dp_a[n] = dp_a[n-1]
    dp_ab[n] = (dp_ab[n-1] + dp_a[n-1])%MOD
    dp_abc[n] = dp_abc[n-1]
  when c
    dp_none[n] = dp_none[n-1]
    dp_a[n] = dp_a[n-1]
    dp_ab[n] = dp_ab[n-1]
    dp_abc[n] = (dp_abc[n-1] + dp_ab[n-1])%MOD
  else
    dp_none[n] = (dp_none[n-1] * 3)%MOD
    dp_a[n] = (dp_a[n-1] * 3 + dp_none[n-1])%MOD
    dp_ab[n] = (dp_ab[n-1] * 3 + dp_a[n-1])%MOD
    dp_abc[n] = (dp_abc[n-1] * 3 + dp_ab[n-1])%MOD
  end
end

p dp_abc[str.size]

Measured memory_bytes: 10232