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++ (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;
#define MOD 1000000007LL
typedef long long ll;

int n;
ll dp[21][51][51][28];
string str[51];

ll solve(int v,int f,int t,int lb){
	if(dp[v][f][t][lb]!=-1)return dp[v][f][t][lb];
	if(f==t)return 1;
	if(str[f].size()==v){
		if(lb==0){
			return solve(v,f+1,t,lb+1);
		}
		else return 0;
	}
	for(int i=f+1;i<t;i++){
		if(str[i].size()==v)return 0;
	}
	ll ans=0;
	for(int i=max(lb,1);i<27;i++){
		for(int j=f;j<t;j++){
			bool flag=true;
			for(int k=f;k<=j;k++){
				if(str[k][v]!='?' && (str[k][v]-'a')!=(i-1)){
					flag=false;
				}
			}
			if(flag){
				ans+=solve(v+1,f,j+1,0)*solve(v,j+1,t,i+1)%MOD;
				ans%=MOD;
			}
		}
	}
	dp[v][f][t][lb]=ans;
	return ans;
}

int main(void){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		cin >> str[i];
	}
	memset(dp,-1,sizeof(dp));
	printf("%lld\n",solve(0,0,n,0));
	return 0;
}