#include "bits/stdc++.h" using namespace std; using ll = long long; using Vi = vector; using Pii = pair; #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()) struct SegTree { using T = int; static constexpr T ID = INT_MAX; struct Node { T extra{ID}; T small{INT_MAX}; void init(T x, int) { small = x; } void merge(const Node& R) { small = min(small, R.small); } void apply(T x, int) { extra = min(extra, x); small = min(small, x); } }; vector V; int len; void init(int n, T def) { for (len = 1; len < n; len *= 2); V.assign(len*2, {}); rep(i, len, len+n) V[i].init(def, 1); for (int i = len-1; i > 0; i--) update(i); } int L(int i) { return i*2; } int R(int i) { return i*2+1; } void update(int i) { int a = L(i), b = R(i); V[i] = {}; V[i].merge(V[a]); V[i].merge(V[b]); } void push(int i, int size) { int e = V[i].extra; if (e != ID) { V[L(i)].apply(e, size/2); V[R(i)].apply(e, size/2); V[i].extra = ID; } } void modify(int vBegin, int vEnd, T x, int i = 1, int begin = 0, int end = -1) { if (end < 0) end = len; if (vEnd <= begin || end <= vBegin) return; if (vBegin <= begin && end <= vEnd) { V[i].apply(x, end-begin); return; } int m = (begin+end)/2; push(i, end-begin); modify(vBegin,vEnd,x,L(i),begin,m); modify(vBegin,vEnd,x,R(i),m,end); update(i); } Node query(int vBegin, int vEnd, int i = 1, int begin = 0, int end = -1) { if (end < 0) end = len; if (vEnd <= begin || end <= vBegin) return {}; if (vBegin <= begin && end <= vEnd) { return V[i]; } int m = (begin+end)/2; push(i, end-begin); Node x = query(vBegin, vEnd, L(i), begin, m); x.merge(query(vBegin, vEnd, R(i), m, end)); return x; } }; constexpr int INF = 1e8; struct Aho { enum{alpha=26, first='a'}; struct Node { int back, next[alpha], start = -1, end = -1, maxMatch = 0; Node(int v) { memset(next, v, sizeof(next)); } }; vector N; Vi backp; void insert(string& s, int j) { assert(!s.empty()); int n = 0; each(c, s) { int& m = N[n].next[c-first]; if (m == -1) { n = m = sz(N); N.emplace_back(-1); } else { n = m; } } if (N[n].end == -1) N[n].start = j; backp.pb(N[n].end); N[n].end = j; N[n].maxMatch = sz(s); } Aho(vector& pat) { N.emplace_back(-1); rep(i, 0, sz(pat)) insert(pat[i], i); N[0].back = sz(N); N.emplace_back(0); queue q; for (q.push(0); !q.empty(); q.pop()) { int n = q.front(), prev = N[n].back; rep(i, 0, alpha) { int &ed = N[n].next[i], y = N[prev].next[i]; if (ed == -1) ed = y; else { N[ed].back = y; (N[ed].end == -1 ? N[ed].end : backp[N[ed].start]) = N[y].end; N[ed].maxMatch = max(N[ed].maxMatch, N[y].maxMatch); q.push(ed); } } } } int solve(string& target) { int n = 0; SegTree tree; tree.init(sz(target)+1, INF); tree.modify(0, 1, 0); rep(i, 0, sz(target)) { char chr = target[i]; n = N[n].next[chr-first]; int reach = i+1 - N[n].maxMatch; if (reach < i+1) { auto v = tree.query(reach-1, reach); tree.modify(reach, i+1, v.small+1); } } return tree.query(sz(target), sz(target)+1).small; } }; int main() { cin.sync_with_stdio(0); cin.tie(0); cout << fixed << setprecision(18); int n; cin >> n; string target; cin >> target; vector ziomki(n); each(z, ziomki) cin >> z; Aho aho(ziomki); auto xd = aho.solve(target); cout << (xd < INF-5 ? xd : -1) << endl; return 0; }