#include #include #include #include #include #include #include using namespace std; typedef set SS; typedef vector VS; struct Key { int word, off, len, used; Key(int word, int off, int len, int used) : word(word), off(off), len(len), used(used) {} bool operator < (const Key &o) const { if (word != o.word) return word < o.word; if (off != o.off) return off < o.off; if (len != o.len) return len < o.len; return used < o.used; } }; typedef map MKI; string target; VS pattern; MKI cache; int solve(int word, int off, int len, bool word_used) { Key key(word, off, len, word_used ? 1 : 0); if (word >= pattern.size()) { return len >= target.size() ? 1 : 0; } if (off >= pattern[word].size()) { if (!word_used) return 0; return solve(word + 1, 0, len, false); } if (cache.count(key)) return cache[key]; int count = solve(word, off + 1, len, word_used); if (len < target.size() && pattern[word][off] == tolower(target[len])) { count += solve(word, off + 1, len + 1, true); } return cache[key] = count; } int main(void) { while (1) { int n; cin >> n; if (n == 0) break; SS ignore; while (n--) { string s; cin >> s; ignore.insert(s); } while (1) { cache.clear(); cin >> target; cin.ignore(1); string line; getline(cin, line); if (target == "LAST" && line == "CASE") break; pattern.clear(); istringstream in(line); while (1) { string s; in >> s; if (in.fail()) break; if (!ignore.count(s)) pattern.push_back(s); } int result = solve(0, 0, 0, false); if (result == 0) cout << target << " is not a valid abbreviation" << endl; else cout << target << " can be formed in " << result << " ways" << endl; } } return 0; }