phrases
. Your task is to find all unique phrases that can be formed by concatenating two different phrases from the list, such that the last word of the first phrase is the same as the first word of the second phrase. The resulting phrase should not repeat the shared word.
["writing code", "code rocks"]
["writing code rocks"]
first word
to a list of phrase indices that start with that word.last word
.first word
matches this last word
.["writing code", "code rocks", "rocks and rolls", "code writing"]
["code rocks and rolls", "code writing code", "writing code rocks", "writing code writing"]
from collections import defaultdict
class Solution:
def beforeAndAfterPuzzles(self, phrases):
first_word_map = defaultdict(list)
n = len(phrases)
for i, phrase in enumerate(phrases):
first = phrase.split()[0]
first_word_map[first].append(i)
res = set()
for i, phrase in enumerate(phrases):
words = phrase.split()
last = words[-1]
if last in first_word_map:
for j in first_word_map[last]:
if i == j:
continue
# Combine phrase i and j, omitting the duplicate word
combined = phrase + phrases[j][len(last):]
res.add(combined.strip())
return sorted(res)
#include <vector>
#include <string>
#include <unordered_map>
#include <set>
#include <algorithm>
using namespace std;
class Solution {
public:
vector<string> beforeAndAfterPuzzles(vector<string>& phrases) {
unordered_map<string, vector<int>> first_word_map;
int n = phrases.size();
for (int i = 0; i < n; ++i) {
string first = phrases[i].substr(0, phrases[i].find(' '));
first_word_map[first].push_back(i);
}
set<string> res;
for (int i = 0; i < n; ++i) {
string phrase = phrases[i];
size_t pos = phrase.rfind(' ');
string last = (pos == string::npos) ? phrase : phrase.substr(pos + 1);
if (first_word_map.count(last)) {
for (int j : first_word_map[last]) {
if (i == j) continue;
string to_add = phrase;
string tail = phrases[j].substr(last.length());
if (!tail.empty() && tail[0] == ' ') tail = tail.substr(1);
if (!tail.empty()) to_add += " " + tail;
res.insert(to_add);
}
}
}
return vector<string>(res.begin(), res.end());
}
};
import java.util.*;
class Solution {
public List<String> beforeAndAfterPuzzles(String[] phrases) {
Map<String, List<Integer>> firstWordMap = new HashMap<>();
int n = phrases.length;
for (int i = 0; i < n; ++i) {
String first = phrases[i].split(" ")[0];
firstWordMap.computeIfAbsent(first, k -> new ArrayList<>()).add(i);
}
Set<String> res = new TreeSet<>();
for (int i = 0; i < n; ++i) {
String[] words = phrases[i].split(" ");
String last = words[words.length - 1];
if (firstWordMap.containsKey(last)) {
for (int j : firstWordMap.get(last)) {
if (i == j) continue;
String tail = phrases[j].substring(last.length());
String combined = phrases[i] + tail;
res.add(combined.trim());
}
}
}
return new ArrayList<>(res);
}
}
/**
* @param {string[]} phrases
* @return {string[]}
*/
var beforeAndAfterPuzzles = function(phrases) {
const firstWordMap = {};
for (let i = 0; i < phrases.length; ++i) {
const first = phrases[i].split(' ')[0];
if (!firstWordMap[first]) firstWordMap[first] = [];
firstWordMap[first].push(i);
}
const res = new Set();
for (let i = 0; i < phrases.length; ++i) {
const words = phrases[i].split(' ');
const last = words[words.length - 1];
if (firstWordMap[last]) {
for (let j of firstWordMap[last]) {
if (i === j) continue;
const tail = phrases[j].substring(last.length);
let combined = phrases[i] + tail;
res.add(combined.trim());
}
}
}
return Array.from(res).sort();
};