1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <bits/stdc++.h>
#ifdef LOC
#include "debuglib.h"
#else
#define deb(...)
#define DBP(...)
#endif
using namespace std;
using   ll         = long long;
using   vi         = vector<int>;
using   pii        = pair<int, int>;
#define pb           push_back
#define mp           make_pair
#define x            first
#define y            second
#define rep(i, b, e) for (int i = (b); i < (e); i++)
#define each(a, x)   for (auto& a : (x))
#define all(x)       (x).begin(), (x).end()
#define sz(x)        int((x).size())

constexpr int MOD = 1e9+7;

ll modPow(ll a, ll e, ll m) {
	ll t = 1 % m;
	while (e) {
		if (e % 2) t = t*a % m;
		e /= 2; a = a*a % m;
	}
	return t;
}

struct Zp {
	ll x;
	Zp() : x(0) {}
	Zp(ll a) : x(a%MOD) { if (x < 0) x += MOD; }
	#define OP(c,d) Zp& operator c##=(Zp r) { x = x d; return *this; } Zp operator c(Zp r) const { Zp t = *this; return t c##= r; }
	OP(+, +r.x - MOD*(x+r.x >= MOD));
	OP(-, -r.x + MOD*(x-r.x < 0));
	OP(*, *r.x % MOD);
	OP(/, *r.inv().x % MOD);
	Zp operator-() const { return Zp()-*this; }
	Zp inv() const { return pow(MOD-2); }
	Zp pow(ll e) const{ return modPow(x,e,MOD); }
	void print() { cerr << x; }
};

template<class F>
vector<vector<Zp>> getDP(int n, F isUp) {
	vector<vector<Zp>> dp(n+1, vector<Zp>(n+1));
	dp[0][0] = 1;
	rep(i, 1, n+1) {
		int d = (isUp(i-1) ? 1 : -1);
		int j = i-1;
		while (j > 0 && isUp(j-1) != isUp(i-1)) j--;
		int from = max(d, 0), to = min(n+d, n)+1;
		rep(b, from, to) {
			rep(k, j, i) {
				dp[i][b] += dp[k][b-d];
			}
		}
	}
	return dp;
}

void run() {
	int n; cin >> n;
	vector<string> elems(n);
	each(e, elems) cin >> e;

	vector<Zp> inPref(n);
	vector<vector<Zp>> prefForL(n), prefForR(n), sufL(n), sufR(n);

	rep(i, 0, n) {
		string& s = elems[i];
		auto pref = getDP(sz(s), [&](int j) { return s[j] == 'L'; });
		auto suf = getDP(sz(s), [&](int j) { return s[sz(s)-j-1] == 'P'; });

		prefForL[i].resize(sz(s)+1);
		prefForR[i].resize(sz(s)+1);
		sufL[i].resize(sz(s)+1);
		sufR[i].resize(sz(s)+1);

		rep(j, 0, sz(s)) {
			inPref[i] += pref[j+1][0];
		}
		for (int j = sz(s);; j--) {
			rep(b, 0, sz(s)+1) prefForL[i][b] += pref[j][b];
			if (j <= 0 || s[j-1] == 'L') break;
		}
		for (int j = sz(s);; j--) {
			rep(b, 0, sz(s)+1) prefForR[i][b] += pref[j][b];
			if (j <= 0 || s[j-1] == 'P') break;
		}
		rep(j, 0, sz(s)) {
			auto &out = (s[j] == 'P' ? sufR[i] : sufL[i]);
			rep(b, 0, sz(s)+1) out[b] += suf[sz(s)-j][b];
		}
	}

	rep(i, 0, n) {
		rep(j, 0, n) {
			Zp ans = inPref[i];
			rep(b, 0, min(sz(elems[i]), sz(elems[j]))+1) {
				ans += prefForL[i][b] * sufL[j][b];
				ans += prefForR[i][b] * sufR[j][b];
			}
			cout << ans.x << ' ';
		}
		cout << '\n';
	}
}

int main() {
	cin.sync_with_stdio(0); cin.tie(0);
	cout << fixed << setprecision(10);
	run();
	cout << flush; _Exit(0);
}