#include <iostream> #include <map> #include <stack> #include <stddef.h> #include <string> #include <vector> using namespace std; class TrieNode { public: bool suffixEnd; map<char, TrieNode*> children; TrieNode() { suffixEnd = false; } TrieNode* getChild(char ch) { return children[ch]; } TrieNode* newChild(char ch) { return children[ch] = new TrieNode; } }; class Trie { public: TrieNode* root; Trie() { root = new TrieNode; } void insertSuffixes(string word) { int len = word.length(); for (int i = 0; i < len; i++) { TrieNode* node = root; for (int j = i; j < len; j++) { char ch = word[j]; if (node->getChild(ch) != NULL) node = node->getChild(ch); else node = node->newChild(ch); } node->suffixEnd = true; } } }; // Finds longest common substring between two given strings // end1 and end2 must not be contained in the text, change values accordingly class LongestCommonSubstrings { private: const static char end1 = '!'; const static char end2 = '@'; static pair<bool, bool> findRecursive(TrieNode* node, deque<char> & path_to_root, int depth, vector<string> & substrings, int & longest_found) { int children_count = 0; bool subtreeHasEnd1 = false, subtreeHasEnd2 = false; for (map<char, TrieNode*>::iterator I = node->children.begin(); I != node->children.end(); I++) { children_count++; path_to_root.push_back(I->first); pair<bool, bool> hasEnds = findRecursive(I->second, path_to_root, depth + 1, substrings, longest_found); subtreeHasEnd1 = subtreeHasEnd1 || I->first == end1 || hasEnds.first; subtreeHasEnd2 = subtreeHasEnd2 || I->first == end2 || hasEnds.second; path_to_root.pop_back(); } if ((children_count >= 2 || (children_count == 1 && node->suffixEnd)) && (subtreeHasEnd1 && subtreeHasEnd2)) { if (depth > longest_found) { substrings.clear(); substrings.push_back(string(path_to_root.begin(), path_to_root.end())); longest_found = depth; } else if (depth == longest_found) { substrings.push_back(string(path_to_root.begin(), path_to_root.end())); } } return make_pair(subtreeHasEnd1, subtreeHasEnd2); } public: static vector<string> findAll(const string & word1, const string & word2) { Trie trie = Trie(); trie.insertSuffixes(word1 + end1); trie.insertSuffixes(word2 + end2); vector<string> substrings; deque<char> path_to_root; int longest_found = 0; findRecursive(trie.root, path_to_root, 0, substrings, longest_found); return substrings; } }; int main() { string a, b, c; int cases = 0; while (true) { cases++; if (cases > 1) getline(cin, c); if (getline(cin, a)) { getline(cin, b); } else break; if (cases > 1) cout << endl; vector<string> sol = LongestCommonSubstrings::findAll(a, b); if (sol.empty() || (sol.size() == 1 && sol[0].length() == 0)) cout << "No common sequence." << endl; else for (int i = 0; i < sol.size(); i++) cout << sol[i] << endl; } return 0; }
Thursday, April 23, 2015
UVa 760 - DNA Sequencing
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment