解法.
上の全順序は
通りあるので全順序を全列挙して式
を評価するという方針では間に合いません。そこで、式
と
の値が
となる全順序が何通りあるのかを求めることを考えます。
下の式の構文木で
を A として考察します。A が式の値となるためには A となる葉の少なくともひとつが、その葉から根までの経路の評価で勝ち続ける必要があります。例えば NWEAS という全順序を考えたときには左にある A が勝ち続けるので、全順序 NWEAS に対する式の値は A となります。また、A よりも小さい要素を並び替えた WENAS や WNEAS なども式の値は A となります。

ここで、A よりも小さい要素と大きい要素の集合をそれぞれ
とします(上の例では
)。
内の要素の順序が異なるどの全順序に対しても式の値が A となるかどうかは変わりません。なぜならば、式の値が A かどうかが変わるということは、A を葉とする頂点から根までの経路中に評価が反転する頂点があるということになります。しかし、木の高さによる帰納法から
内の要素の順序を変えただけでは評価が反転することがないことが分かります。
また、
が固定されたときの式の値は
時間で求めることができ、そのときの全順序の種類数は
となることが分かります。
の選び方は
通りあるので、各
に対して
よりも小さい要素と大きい集合を全探索して式の値を評価しても間に合います。
計算時間: 
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;
class IcpcanAlphabet {
public:
explicit IcpcanAlphabet(const int max_n) : fact(max_n + 1), cmp(26) {
fact[0] = 1;
for (int i = 1; i <= max_n; ++i) fact[i] = i * fact[i - 1];
}
ll GetNumTotalOrderEqualExp(const std::string &A, const std::string &S, const std::string &T) {
const int N = A.size();
ll num = 0;
for (int i = 0; i < N; ++i) {
cmp[index(A[i])] = 0;
const unsigned int univ = ((1 << N) - 1) ^ (1 << i);
unsigned int sub = univ;
while (true) {
int num_less = 0;
for (int j = 0; j < N; ++j) {
if (sub >> j & 1) {
++num_less;
cmp[index(A[j])] = -1;
}
else if (i != j) {
cmp[index(A[j])] = 1;
}
}
auto it_s = S.begin(), it_t = T.begin();
if (Evaluate(it_s) == 0 && Evaluate(it_t) == 0)
num += fact[num_less] * fact[N - num_less - 1];
if (sub == 0) break;
sub = (sub - 1) & univ;
}
}
return num;
}
private:
std::vector<ll> fact;
std::vector<int> cmp;
unsigned index(const char c) const { return static_cast<unsigned>(c - 'A'); }
int Evaluate(std::string::const_iterator& it) {
if (*it == '(') {
int lhs = Evaluate(++it);
char op = *it;
int rhs = Evaluate(++it);
++it;
return (op == '<') ? std::min(lhs, rhs) : std::max(lhs, rhs);
}
else {
return cmp[index(*it++)];
}
}
};
int main() {
const int MAX_N = 16;
IcpcanAlphabet solver(MAX_N);
int n;
while (std::cin >> n, n) {
std::string a, s, t;
std::cin >> a >> s >> t;
std::cout << solver.GetNumTotalOrderEqualExp(a, s, t) << std::endl;
}
return 0;
}
競プロから遠ざかっていたので大変だった。コンテスト時間内で解いている人スゴイな。