#include using namespace std; #define rep(i, n) for(int i = 0; i < n; i++) #define rep2(i, x, n) for(int i = x; i <= n; i++) #define rep3(i, x, n) for(int i = x; i >= n; i--) #define elif else if #define sp(x) fixed << setprecision(x) #define pb push_back #define eb emplace_back #define all(x) x.begin(), x.end() #define sz(x) (int)x.size() using ll = long long; using ld = long double; using pii = pair; using pil = pair; using pli = pair; using pll = pair; const ll MOD = 1e9+7; //const ll MOD = 998244353; const int inf = (1<<30)-1; const ll INF = (1LL<<60)-1; const ld EPS = 1e-10; template bool chmax(T &x, const T &y) {return (x < y)? (x = y, true) : false;}; template bool chmin(T &x, const T &y) {return (x > y)? (x = y, true) : false;}; struct Suffix_Array{ const string s; const int n, log_n, m; vector> sa, ord; int log_2(int k){ int ret = 0; while((1<(log_n+1)); ord.assign(n, vector(log_n+1)); vector cnt(m, 0); rep(i, n) cnt[s[i]]++; rep(i, m-1) cnt[i+1] += cnt[i]; rep(i, n) sa[--cnt[s[i]]][0] = i; ord[sa[0][0]][0] = 0; rep2(i, 1, n-1){ int a = sa[i-1][0], b = sa[i][0]; ord[b][0] = ord[a][0] + (s[a] < s[b]); } fill(all(cnt), 0); vector tmp(n); rep(k, log_n){ rep(i, n) tmp[i] = sa[i][k]+(n-(1< &SA, vector &ORD){ SA.resize(n), ORD.resize(n); vector cnt(m, 0); int sum = 0; vector tmp(n), memo(n); rep(k, log_n+1){ if(!(l&(1< lcp, ord; Longest_Common_Prefix_Array(const Suffix_Array &sa) : sa(sa), n(sa.size()-1){ lcp.assign(n, 0), ord.assign(n+1, 0); lcp[0] = 0; rep(i, n+1) ord[sa[i]] = i; int h = 0; rep(i, n){ int j = sa[ord[i]-1]; if(h > 0) h--; while(max(i, j)+h < n && sa.s[i+h] == sa.s[j+h]) h++; lcp[ord[i]-1] = h; } } int operator [] (int i) const {return lcp[i];} }; template struct Segment_Tree{ Monoid ope(Monoid a, Monoid b){ return min(a, b); } const Monoid unit; int n; vector seg; Segment_Tree(int N, const Monoid &x) : unit(x){ n = 1; while(n < N) n <<= 1; seg.assign(2*n, unit); } void change(int i, const Monoid &x){ i += n; seg[i] = x; while(i > 0){ i /= 2; seg[i] = ope(seg[2*i], seg[2*i+1]); } } Monoid query(int a, int b, int i = 1, int l = 0, int r = -1){ if(r < 0) r = n; if(a >= r || b <= l) return unit; if(a <= l && r <= b) return seg[i]; Monoid vl = query(a, b, 2*i, l, (l+r)/2); Monoid vr = query(a, b, 2*i+1, (l+r)/2, r); return ope(vl, vr); } Monoid operator [] (int i) const {return seg[n+i];} void clear(){ fill(seg.begin(), seg.end(), unit); } }; int main(){ ll N; cin >> N; string s[N]; rep(i, N) cin >> s[i]; int n = 0, pos[N]; rep(i, N) pos[i] = n, n += sz(s[i]); string S(n, 'a'); rep(i, N){ rep(j, sz(s[i])) S[pos[i]+j] = s[i][j]; } Suffix_Array sa(S); vector ord(n+1); rep(i, n+1) ord[sa[i]] = i; Longest_Common_Prefix_Array lcp(sa); Segment_Tree seg(n, inf); rep(i, n) seg.change(i, lcp[i]); int M; ll x, d; cin >> M >> x >> d; ll ans = 0; rep(i, M){ int a = x/(N-1), b = x%(N-1); if(a > b) swap(a, b); else b++; int tmp = min(sz(s[a]), sz(s[b])); a = ord[pos[a]], b = ord[pos[b]]; if(a > b) swap(a, b); //chmin(tmp, seg.query(a, b)); ans += tmp; x += d, x %= N*(N-1); } cout << ans << endl; }