Advertisement
Guest User

Untitled

a guest
Dec 8th, 2016
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.14 KB | None | 0 0
  1. #include <cmath>
  2. #include <cstdio>
  3. #include <string>
  4. #include <vector>
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <stack>
  8. #include <utility>
  9. #include <map>
  10. #include <unordered_map>
  11. #include <deque>
  12. #include <queue>
  13. using namespace std;
  14.  
  15. int score(const string &s) {
  16. int r = 0;
  17. for(const auto &c : s) {
  18. if(c == 'A' || c == 'E' || c == 'I' || c == 'L' || c == 'N' || c == 'O' || c == 'R' || c == 'S' || c == 'T' || c == 'U') r += 1;
  19. else if(c == 'D' || c == 'G') r += 2;
  20. else if(c == 'B' || c == 'C' || c == 'M' || c == 'P') r+= 3;
  21. else if(c == 'F' || c == 'H' || c == 'V' || c == 'W' || c == 'Y') r += 4;
  22. else if(c == 'K') r += 5;
  23. else if(c == 'J' || c == 'X') r += 8;
  24. else if (c == 'Q' || c == 'Z') r += 10;
  25. }
  26. return r;
  27. }
  28.  
  29. using pii = pair<int, deque<int>>;
  30.  
  31. int main() {
  32. size_t K; cin >> K;
  33. size_t N; cin >> N;
  34.  
  35. multimap<string, int> edge_ids;
  36. vector<vector<int>> edges;
  37. vector<int> scores;
  38.  
  39. // Build graph (ie replcae each character with '_' and attach to all other nodes that have the same hash)
  40. for(size_t i = 0; i < N; i++) {
  41. string s; cin >> s;
  42. if(s.length() != K) continue;
  43. int id = scores.size();
  44. scores.push_back(score(s));
  45. edges.push_back({});
  46. for(size_t j = 0; j < s.length(); j++) {
  47. char t = s[j];
  48. s[j] = '_';
  49.  
  50. auto range = edge_ids.equal_range(s);
  51. for (auto k = range.first; k != range.second; ++k)
  52. {
  53. edges[k->second].push_back(id);
  54. edges[id].push_back(k->second);
  55. }
  56. edge_ids.insert({s, id});
  57. s[j] = t; // replace character
  58. }
  59. }
  60.  
  61. // Find global maximums in graph! We know the "middle" of the ladder will be higher than both of its neighbouring elements
  62. // so we only need to start looking there.
  63. priority_queue<pii> peaks;
  64. for(size_t i = 0; i < scores.size(); ++i) {
  65. int num_less = 0;
  66. for(auto e : edges[i]) if(scores[e] < scores[i]) num_less ++;
  67. if(!edges[i].size() || num_less >= 2) peaks.push({scores[i], {(int)i}});
  68. }
  69.  
  70. // Do prioritized BFS on sequences, expanding each sequence TWO at a time (we know that if this sequence
  71. // can't get longer on one edge then we're done!
  72. int bestLadder = 0;
  73. unordered_map<int, pair<int, int>> visited;
  74. while(!peaks.empty()) {
  75. pii top = peaks.top();
  76. peaks.pop();
  77. auto v = top.second;
  78. int left = v.front();
  79. int right = v.back();
  80. // Check if another sequence has viewed this node
  81. // If the score was higher AND the sequence was longer
  82. // we continue. Otherwise this sequence may prove to be better.
  83. if(visited[left].first > top.first) {
  84. if(visited[left].second > v.size()) continue;
  85. }
  86. if(visited[right].first > top.first) {
  87. if(visited[right].second > v.size()) continue;
  88. }
  89. visited[left] = visited[right] = {top.first, v.size()};
  90. // Build list of expansion edges for left && right end of sequence
  91. vector<int> lc, rc;
  92. for(auto e : edges[left]) {
  93. if(e == left || e == right) continue;
  94. if(scores[e] < scores[left]) {
  95. lc.push_back(e);
  96. }
  97. }
  98. for(auto e : edges[right]) {
  99. if(e == left || e == right) continue;
  100. if(scores[e] < scores[right]) {
  101. rc.push_back(e);
  102. }
  103. }
  104. // If there are no more nodes to add then this sequence is done and we can
  105. // compare it with the best ladder seen so far.
  106. if(!lc.size() || !rc.size()) { // End of chain
  107. bestLadder = std::max(bestLadder, top.first);
  108. }
  109. else { // Add sequence to frontier
  110. for(int a : lc) {
  111. for(int b : rc) {
  112. if(b == a) continue;
  113. deque<int> l = top.second;
  114. l.push_front(a);
  115. l.push_back(b);
  116. peaks.push({top.first + scores[a] + scores[b], l});
  117. }
  118. }
  119. }
  120. }
  121. cout << bestLadder << endl;
  122. return 0;
  123. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement