An array of N words is given. Each word consists of small letters (‘a’- ‘z’). Our goal is to concatenate the words in such a say as to obtain a single word with the longest possible sub-string composed of one particular letter. Find the length of such a sub-string.
Examples:
Given N=3 and words=[‘aabb’,’aaaa’,’bbab’], your function should return 6. One of the best concatenations is words[1]+words[0]+words[2]=’aaaaaabbbbab’. The longest sub-string is composed of the letter ‘a’ and its length is 6.
Given N=3 and words=[‘xxbxx’,’xbx’,’x’], your function should return 4. One of the best concatenations is words[0]+words[2]+words[1]=’xxbxxxxbx’. The longest sub-string is composed of letter ‘x’ and its length is 4.
I know I should not be posting the answer, But might help someone who is looking for a optimal solution.
class DailyCodingProblem4 { public static void main(String args[]) { String[] arr = { "aabb", "aaaa", "bbab" }; int res = solution(arr); System.out.println(res); String[] arr2 = { "xxbxx", "xbx", "x" }; res = solution(arr2); System.out.println(res); } private static int solution(String[] arr) { Map<Integer, Integer> prefix = new HashMap<>(); Map<Integer, Integer> suffix = new HashMap<>(); Map<Integer, Integer> both = new HashMap<>(); for (int i = 0; i < arr.length; i++) { String word = arr[i]; int j = 1; while (j < word.length() && word.charAt(0) == word.charAt(j)) { j++; } int key = word.charAt(0); if (j == word.length()) { if (both.containsKey(key)) { Integer temp = both.get(key); if (j > temp) { both.put(key, j); } } else { both.put(key, j); } } else { if (suffix.containsKey(key)) { Integer temp = suffix.get(key); if (j > temp) { suffix.put(key, j); } } else { suffix.put(key, j); } j = word.length() - 1; while (j > 0 && word.charAt(word.length() - 1) == word.charAt(j - 1)) { j--; } key = word.charAt(word.length() - 1); if (prefix.containsKey(key)) { Integer temp = prefix.get(key); if (word.length() - j > temp) { prefix.put(key, word.length() - j); } } else { prefix.put(key, word.length() - j); } } } int res = 0; for (Integer key : prefix.keySet()) { if (suffix.containsKey(key)) { int temp = prefix.get(key) + suffix.get(key); if (temp > res) { res = temp; } } } for (Integer key : suffix.keySet()) { if (prefix.containsKey(key)) { int temp = prefix.get(key) + suffix.get(key); if (temp > res) { res = temp; } } } for (Integer key : both.keySet()) { if (prefix.containsKey(key)) { int temp = prefix.get(key) + both.get(key); if (temp > res) { res = temp; } } if (suffix.containsKey(key)) { int temp = both.get(key) + suffix.get(key); if (temp > res) { res = temp; } } } return res; } }
Advertisement
Answer
For each letter, you need to know:
- the total length of words consisting entirely of that letter;
- the words with the longest and second-longest prefix of that letter; and
- the words with the longest and second-longest suffix of that letter
Since each word goes in at most 2 of these groups, determined by the letters it starts and ends with, you can figure this all out in O(N) time.