#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector")
#define _USE_MATH_DEFINED
#include <bits/stdc++.h>
using namespace std;
namespace utility {
  //typedef
  typedef long long ll;
  typedef unsigned long long ull;
  typedef long double ld;
  typedef vector<int> vi;
  typedef vector<ll> vll;
  typedef pair<int,int> ii;
  typedef vector<ii> vii;
  typedef tuple<int,int,int> iii;
  typedef tuple<int,int,int,int> iiii;
  template<typename T,typename Compare=greater<T>>
  using pq = priority_queue<T,vector<T>,Compare>;
  constexpr ll LINF = (ll)1e18+42;
  constexpr ll INF = (ll)1e9+42;
  constexpr ll MOD = (ll)1e9+7;
  constexpr ld EPS = 1e-9;
  seed_seq SEED{
    (uint64_t) chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count()
    ,(uint64_t) __builtin_ia32_rdtsc()
  #if __cplusplus >= 201402L
    ,(uint64_t) (uintptr_t) make_unique<char>().get()
  #endif
  };
  const int RAND = minstd_rand(SEED)();
  //macros
  #define sz(x) int((x).size())
  #define fi first
  #define se second
  #define g(i,t) get<i>(t)
  #define gcd __gcd
  #define bcount __builtin_popcount
  #define clz __builtin_clz
  #define ctz __builtin_ctz
  //functions
  template<typename T>
  T sq(T a) { return a*a; }
  #if __cplusplus >= 201402L
  template<typename Arg>
  Arg min(const Arg& arg) { return arg; }
  template<typename Arg,typename ...Args>
  auto min(const Arg& arg,const Args&... args) { auto m = min(args...); return arg < m ? arg : m; }
  template<typename Arg>
  Arg max(const Arg& arg) { return arg; }
  template<typename Arg,typename ...Args>
  auto max(const Arg& arg,const Args&... args) { auto m = max(args...); return arg > m ? arg : m; }
  #endif
  //I/O
  #ifdef EVAL
  ifstream in("input.txt");
  ofstream out("output.txt");
  #define cin in
  #define cout out
  #endif
  template<typename Arg>
  void read(Arg& arg) { cin>>arg; }
  template<typename ...Types>
  void read(pair<Types...>&);
  template<typename ...Types>
  void read(tuple<Types...>&);
  template<typename ...Types>
  void read(vector<Types...>&);
  template<typename ...Types>
  void read(deque<Types...>&);
  template<typename Type,size_t N>
  void read(array<Type,N>&);
  template<typename ...Types>
  void read(list<Types...>&);
  template<size_t I=0,typename Tuple>
  typename enable_if<I >= tuple_size<Tuple>::value>::type
    read_tuple(Tuple&) {}
  template<size_t I=0,typename Tuple>
  typename enable_if<I < tuple_size<Tuple>::value>::type
    read_tuple(Tuple& x) { read(get<I>(x)); read_tuple<I+1>(x); }
  template<typename ...Types>
  void read(pair<Types...>& x) { read_tuple(x); }
  template<typename ...Types>
  void read(tuple<Types...>& x) { read_tuple(x); }
  template<typename ...Types>
  void read(vector<Types...>& x) { for(auto& i : x) read(i); }
  template<typename ...Types>
  void read(deque<Types...>& x) { for(auto& i : x) read(i); }
  template<typename Type,size_t N>
  void read(array<Type,N>& x) { for(auto& i : x) read(i); }
  template<typename ...Types>
  void read(list<Types...>& x) { for(auto& i : x) read(i); }
  template<typename Arg,typename ...Args>
  void read(Arg& arg,Args&... args) { read(arg); read(args...); }
  template<typename Arg>
  void print_var(const Arg& arg) { cout<<arg; }
  template<typename ...Types>
  void print_var(const pair<Types...>&);
  template<typename ...Types>
  void print_var(const tuple<Types...>&);
  template<typename ...Types>
  void print_var(const vector<Types...>&);
  template<typename Type,size_t N>
  void print_var(const array<Type,N>&);
  template<typename ...Types>
  void print_var(const deque<Types...>&);
  template<typename ...Types>
  void print_var(const list<Types...>&);
  template<typename ...Types>
  void print_var(const set<Types...>&);
  template<typename ...Types>
  void print_var(const multiset<Types...>&);
  template<typename ...Types>
  void print_var(const map<Types...>&);
  template<typename ...Types>
  void print_var(const unordered_set<Types...>&);
  template<typename ...Types>
  void print_var(const unordered_map<Types...>&);
  template<typename ...Types>
  void print_var(const stack<Types...>&);
  template<typename ...Types>
  void print_var(const priority_queue<Types...>&);
  template<typename ...Types>
  void print_var(const queue<Types...>&);
  template<size_t I=0,typename Tuple>
  typename enable_if<I >= tuple_size<Tuple>::value>::type
    print_tuple(const Tuple&) { if(I == 0) cout.put('('); cout.put(')'); }
  template<size_t I=0,typename Tuple>
  typename enable_if<I < tuple_size<Tuple>::value>::type
    print_tuple(const Tuple& x) { if(I == 0) cout.put('('); else cout.write(", ",2); print_var(get<I>(x)); print_tuple<I+1>(x); }
  template<typename List>
  void print_list(const List& x) { cout.put('['); bool first = true; for(const auto& i : x) { if(!first) cout.write(", ",2); first = false; print_var(i); } cout.put(']'); }
  template<typename Set>
  void print_set(const Set& x) { cout.put('{'); bool first = true; for(const auto& i : x) { if(!first) cout.write(", ",2); first = false; print_var(i); } cout.put('}'); }
  template<typename Map>
  void print_map(const Map& x) { cout.put('{'); bool first = true; for(const auto& i : x) { if(!first) cout.write(", ",2); first = false; print_var(i.fi); cout.put(':'); print_var(i.se); } cout.put('}'); }
  template<typename Stack>
  void print_stack(const Stack& x) { Stack y(x); cout.put('['); bool first = true; while(!y.empty()) { if(!first) cout.write(", ",2); first = false; print_var(y.top()); y.pop(); } cout.put(']'); }
  template<typename ...Types>
  void print_var(const queue<Types...>& x) { queue<Types...> y(x); cout.put('['); bool first = true; while(!y.empty()) { if(!first) cout.write(", ",2); first = false; print_var(y.front()); y.pop(); } cout.put(']'); }
  template<typename ...Types>
  void print_var(const pair<Types...>& x) { print_tuple(x); }
  template<typename ...Types>
  void print_var(const tuple<Types...>& x) { print_tuple(x); }
  template<typename ...Types>
  void print_var(const vector<Types...>& x) { print_list(x); }
  template<typename Type,size_t N>
  void print_var(const array<Type,N>& x) { print_list(x); }
  template<typename ...Types>
  void print_var(const deque<Types...>& x) { print_list(x); }
  template<typename ...Types>
  void print_var(const list<Types...>& x) { print_list(x); }
  template<typename ...Types>
  void print_var(const set<Types...>& x) { print_set(x); }
  template<typename ...Types>
  void print_var(const multiset<Types...>& x) { print_set(x); }
  template<typename ...Types>
  void print_var(const map<Types...>& x) { print_map(x); }
  template<typename ...Types>
  void print_var(const unordered_set<Types...>& x) { print_set(x); }
  template<typename ...Types>
  void print_var(const unordered_map<Types...>& x) { print_map(x); }
  template<typename ...Types>
  void print_var(const stack<Types...>& x) { print_stack(x); }
  template<typename ...Types>
  void print_var(const priority_queue<Types...>& x) { print_stack(x); }
  template<typename Arg>
  void print(const Arg& arg) { print_var(arg); cout.put('\n'); }
  template<typename Arg,typename ...Args>
  void print(const Arg& arg,const Args&... args) { print_var(arg); cout.put(' '); print(args...); }
  template<typename Arg>
  void print_raw(const Arg& arg) { cout<<arg; }
  template<typename ...Types>
  void print_raw(const pair<Types...>&);
  template<typename ...Types>
  void print_raw(const vector<Types...>&);
  template<typename Type,size_t N>
  void print_raw(const array<Type,N>&);
  template<typename ...Types>
  void print_raw(const deque<Types...>&);
  template<typename ...Types>
  void print_raw(const list<Types...>&);
  template<typename ...Types>
  void print_raw(const set<Types...>&);
  template<typename List>
  void print_raw_list(const List& x) { bool first = true; for(auto& i : x) { if(!first) cout.put(' '); first = false; print_raw(i); } }
  template<typename ...Types>
  void print_raw(const pair<Types...>& x) { print_raw(x.fi); cout.put(' '); print_raw(x.se); }
  template<typename ...Types>
  void print_raw(const vector<Types...>& x) { print_raw_list(x); }
  template<typename Type,size_t N>
  void print_raw(const array<Type,N>& x) { print_raw_list(x); }
  template<typename ...Types>
  void print_raw(const deque<Types...>& x) { print_raw_list(x); }
  template<typename ...Types>
  void print_raw(const list<Types...>& x) { print_raw_list(x); }
  template<typename ...Types>
  void print_raw(const set<Types...>& x) { print_raw_list(x); }
  template<typename Arg,typename ...Args>
  void print_raw(const Arg& arg,const Args&... args) { print_raw(arg); print_raw(args...); }
  #ifdef LOCAL
  void print_dbg(string) { cout.put('\n'); }
  template<typename Arg,typename ...Args>
  void print_dbg(string name,const Arg&arg,const Args&...args){size_t idx=0;for(stack<char>stk;idx<name.size()&&(name[idx]!=','||!stk.empty());++idx){if(name[idx]=='\\'){++idx;continue;}if(name[idx]=='\''||name[idx]=='\"'){if(!stk.empty()&&stk.top()==name[idx])stk.pop();else stk.push(name[idx]);}if((stk.empty()||(stk.top()!='\''&&stk.top()!='\"'))&&(name[idx]=='{'||name[idx]=='('))stk.push(name[idx]);if(name[idx]==')'||name[idx]=='}')stk.pop();}print_raw(name.substr(0,idx),": ");print(arg);print_dbg(name.substr(idx==name.size()?0:idx+1),args...);}
  #define dbg(...) print_dbg(#__VA_ARGS__,__VA_ARGS__)
  #else
  #define dbg(...) asm("nop")
  #endif
}
using namespace utility;

int main()
{
  string S; read(S);
  vector<ll> dp{1,0,0,0};
  for(char& c : S)
  {
    if(c >= 'A')
    {
      dp[c-'A'+1] += dp[c-'A'];
      dp[c-'A'+1] %= MOD;
    }
    else
    {
      for(int i=3; i>0; i--)
      {
        dp[i] += dp[i-1] + dp[i]*2;
        dp[i] %= MOD;
      }
      dp[0] *= 3;
      dp[0] %= MOD;
    }
    dbg(dp);
  }
  print(dp[3]);
  return 0;
}


Measured memory_bytes: 512