#include #include #include #include #include #include #include using namespace std; #define REP(A,B) for(int (A)=0;(A)<(B);(A)++) char buf[333333]; vector patterns; struct AhoCorasick { enum {alpha=26, first='a'}; struct Node { int back, next[alpha], start=-1, end=-1, nmatches=0; Node(int v) { memset(next, v, sizeof(next)); } }; vector N; vector backp; void insert(string& s, int j) { assert(!s.empty()); int n = 0; for(char c : s) { int& m = N[n].next[c-first]; if(m == -1) { n = m = N.size(); N.emplace_back(-1); } else n = m; } if(N[n].end == -1) N[n].start = j; backp.push_back(N[n].end); N[n].end = j; N[n].nmatches++; } AhoCorasick(vector& pat) { N.emplace_back(-1); for(int i = 0; i < pat.size(); i++) { insert(pat[i], i); } N[0].back = N.size(); N.emplace_back(0); queue q; for(q.push(0); !q.empty(); q.pop()) { int n = q.front(), prev = N[n].back; for(int i = 0; i < alpha; i++) { 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].nmatches += N[y].nmatches; q.push(ed); } } } } vector find(string word) { int n = 0; vector res; for(char c : word) { n = N[n].next[c-first]; res.push_back(N[n].end); } return res; } vector< vector > findAll(vector& pat, string word) { vector r = find(word); vector> res(word.size()); for(int i = 0; i < word.size(); i++) { int ind = r[i]; while(ind != -1) { res[i-pat[ind].size()+1].push_back(ind); ind = backp[ind]; } } return res; } }; char maintext[333333]; int LEN; int dp[333333]; const int INF = 444444; vector< int > matches; /* int calc(int pos) { int& ans = dp[pos]; if(pos >= LEN) { return 0; } if(ans == -1) { if(matches[pos].size() == 0) { ans = INF; return ans; } ans = INF; for(int x : matches[pos]) { ans = min(ans, 1+calc(pos+patterns[x].size())); } } return ans; }*/ int main() { int L; scanf("%d", &L); scanf("%s", maintext); LEN = strlen(maintext); REP(i, L) { scanf("%s", buf); patterns.push_back(string(buf)); } AhoCorasick ac(patterns); //reverse(maintext, maintext+LEN); matches = ac.find(string(maintext)); REP(i, 333333) dp[i] = INF; // REP(i, LEN) printf("%d\n", matches[i]); int potrebuju = 0; int dosahnu = LEN; for(int i = LEN-1; i>= 0; i--) { if(matches[i] == -1) { if(dosahnu > i) { printf("-1\n"); return 0; } } potrebuju++; if(matches[i] != -1) { int nejlevejsiIndex = i-patterns[matches[i]].size(); dosahnu = min(nejlevejsiIndex+1, dosahnu); } // printf("i=%d, dosahnu=%d ", i, dosahnu); int dal = dosahnu; for(int j = i-1; j >= dosahnu; j--) { // dp[j] = min(dp[j], dp[i]+1); if(matches[j] != -1) { int aktualni = j-patterns[matches[j]].size()+1; dal = min(dal, aktualni); // nejlevejsiIndex = min(aktualni, nejlevejsiIndex); } } i = dosahnu; dosahnu = dal; // printf("dal=%d\n", dal); } if(dosahnu != 0) printf("-1\n"); else printf("%d\n", potrebuju); return 0; }