#include #include #include #include #include #include using namespace std; int const Letters = 4; int const NA = -1; struct Node { int next [Letters]; Node () { fill (next, next + Letters, NA); } bool isLeaf () const { return (next[0] == NA && next[1] == NA && next[2] == NA && next[3] == NA); } void print() { if (isLeaf()) cout << "---- " << endl; else cout << "A:" << next[0] << " C:" << next[1] << " G:" << next[2] << " T:" << next[3] << endl; } }; struct Trie { vector nodes; Trie(const vector & patterns) { int v = 1; nodes.push_back(Node()); for (int i = 0; i < patterns.size(); i++) { int n = 0; const string& pattern = patterns[i]; for (int j = 0; j < pattern.size(); j++) { int c = letterToIndex(pattern[j]); int next = nodes[n].next[c]; if (next != NA) { n = next; } else { nodes[n].next[c] = v; n = v; nodes.push_back(Node()); v += 1; } } } } int letterToIndex (char letter) { switch (letter) { case 'A': return 0; break; case 'C': return 1; break; case 'G': return 2; break; case 'T': return 3; break; default: assert (false); return -1; } } void print() { for (int i = 0; i < nodes.size(); i++) { cout << i << " " ; nodes[i].print(); } } bool prefixMatch(const string& text) { int n = 0; for( int i = 0; i < text.size(); i++) { int next = nodes[n].next[letterToIndex(text[i])]; if (next == NA) break; n = next; } return nodes[n].isLeaf(); } void match(const string& text, vector& result) { for (int i = 0; i < text.size(); i++) { if (prefixMatch(&text[i])) result.push_back(i); } } }; vector solve (const string& text, int n, const vector & patterns) { vector result; Trie t(patterns); /* t.print(); */ t.match(text, result); return result; } int main (void) { string t; cin >> t; int n; cin >> n; vector patterns (n); for (int i = 0; i < n; i++) { cin >> patterns[i]; } vector ans; ans = solve (t, n, patterns); for (int i = 0; i < (int) ans.size (); i++) { cout << ans[i]; if (i + 1 < (int) ans.size ()) { cout << " "; } else { cout << endl; } } return 0; }