Problem:
すぬけ君の辞書には，n 個の英小文字からなる単語 s1, . . ., sn がのっている．これは辞書順で比較したとき s1 < . . . < sn をみたす．残念ながらいくつかの文字はかすれて読めなくなってしまっている．読めなくなった文字は ? で表される．? を英小文字で置き換えて辞書を復元する方法は何通りあるか，mod 1,000,000,007 でもとめよ．

Constraints

1 ≤ n ≤ 50

1 ≤ |si| ≤ 20

si に現れる文字は英小文字または ? である

Input

n
s1
. . .
sn

Output

答えを一行に出力せよ．

Sample Input 1

2
?sum??mer
c??a??mp

Sample Output 1

703286064

Sample Input 2

3
snuje
????e
snule

Sample Output 2

1

Solution in C++14 (judge verdict: Accepted)

#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
using ll = long long int;
const ll MOD = 1000000007;
const int LEN = 20;

// [l, r) の pos 文字目が v 以上
ll N, dp[55][55][30][30];
char dict[55][30];
char base = (char)('a' - 1);

ll solve(int l, int r, int pos, int v) {
    ll &res = dp[l][r][pos][v];
    if(res >= 0) return res;
    char target = (char)(base + v);

    if(l == r) return res = 1;
    if(v == 27) return res = 0;
    if(pos == LEN) return res = (r - l == 1);

    res = 0;
    for(int k=l; k<=r; k++) {
        if(k > l) {
            if(dict[k-1][pos] != target and dict[k-1][pos] != '?') break;
            if(v == 0 and dict[k-1][pos] == '?') break;
        }
        
        // [l, r) -> [l, k), [k, r)
        ll valL = solve(l, k, pos+1, 0);
        ll valR = solve(k, r, pos, v+1);
        (res += valL * valR) %= MOD;
    }
    return res;
}

int main() {
    cin >> N;
    for(int i=0; i<N; i++) {
        scanf("%s", dict[i]);
        for(int j=strlen(dict[i]); j<LEN; j++) dict[i][j] = base;
    }

    fill(dp[0][0][0], dp[N+1][0][0], -1);
    cout << solve(0, N, 0, 0) << endl;
    return 0;
}