#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; /* Runtime: 1287 ms, faster than 78.08% of C++ online submissions for Palindrome Pairs. Memory Usage: 54.3 MB, less than 98.64% of C++ online submissions for Palindrome Pairs. */ class Solution { public: vector > palindromePairs(vector& words); vector > slow(vector& words); }; /* unsigned long long djb_hash(const string &s) { size_t i; unsigned long long h; h = 0x1505; for (i = 0; i < s.size(); i++) { h = (h << 5) + h + s[i]; } return h; } */ int ispal(string &s, int i, int j) { while (i < j) { if (s[i] != s[j]) return 0; i++; j--; } return 1; } vector > Solution::palindromePairs(vector& words) { int i, j; unsigned long long h; unordered_map m; unordered_map ::iterator mit; int rvs; vector < vector > rv; // Store the hash of each word in a map. // Use the hash as the key, and the index of the word as the val. rvs = 0; for (i = 0; i < words.size(); i++) { string &s = words[i]; h = 0x1505; for (j = 0; j < s.size(); j++) h = (h << 5) + h + s[j]; m[h] = i; } // For each word, go from back to front, and look up the hash // of the suffix in the map. If it's there, and the prefix // is a palindrome, then you have a match! for (i = 0; i < words.size(); i++) { string &s = words[i]; h = 0x1505; for (j = s.size()-1; j >= -1; j--) { mit = m.find(h); if (mit != m.end() && mit->second != i && ispal(s, 0, j)) { rv.resize(rvs+1); rv[rvs].push_back(mit->second); rv[rvs].push_back(i); rvs++; } if (j >= 0) h = (h << 5) + h + s[j]; } } // Throw away the map, and now do the same thing where you // hash the reverses of the strings, and then process the prefixes. m.clear(); for (i = 0; i < words.size(); i++) { string &s = words[i]; h = 0x1505; for (j = s.size()-1; j >= 0; j--) h = (h << 5) + h + s[j]; m[h] = i; } for (i = 0; i < words.size(); i++) { string &s = words[i]; h = 0x1505; for (j = 0; j < s.size(); j++) { mit = m.find(h); if (mit != m.end() && mit->second != i && ispal(s, j, s.size()-1)) { rv.resize(rvs+1); rv[rvs].push_back(i); rv[rvs].push_back(mit->second); rvs++; } if (j >= 0) h = (h << 5) + h + s[j]; } } return rv; } vector > Solution::slow(vector& words) { int i, j, k; string w; vector > rv; vector p; bool ok; p.resize(2); for (i = 0; i < words.size(); i++) { for (j = 0; j < words.size(); j++) { if (j != i) { w = words[i] + words[j]; ok = true; for (k = 0; ok && k < w.size()/2; k++) { ok = (w[k] == w[w.size()-k-1]); } if (ok) { p[0] = i; p[1] = j; rv.push_back(p); } } } } return rv; } int main(int argc, char **argv) { Solution s; string w; vector words; vector < vector < int> > rv; int i; struct timeval t1, t2; double d1, d2; while (cin >> w) words.push_back((w == "-") ? "" : w); gettimeofday(&t1, NULL); d1 = t1.tv_usec; d1 /= 1000000.0; d1 += t1.tv_sec; if (argc > 1 && strchr(argv[1], 's') != NULL) { rv = s.slow(words); for (i = 0; i < rv.size(); i++) printf("%d %d\n", rv[i][0], rv[i][1]); printf("\n"); } rv = s.palindromePairs(words); if (argc > 1 && strchr(argv[1], 'p') != NULL) { for (i = 0; i < rv.size(); i++) printf("%d %d\n", rv[i][0], rv[i][1]); } gettimeofday(&t2, NULL); d2 = t2.tv_usec; d2 /= 1000000.0; d2 += t2.tv_sec; if (argc > 1 && strchr(argv[1], 't') != NULL) { printf("Time: %.3lf\n", d2-d1); } return 0; }