public string solution(string S) { string oneLetterPalindrom = GetOneLetterPalindrom(S); if (oneLetterPalindrom != NoAnswer) { return(oneLetterPalindrom); } List <Word> words = GetWords(S).ToList(); var palindromWord = words.LastOrDefault(w => w.IsPalindrom); if (palindromWord != null) { return(palindromWord.OriginWord); } string result = NoAnswer; var words1 = words.GroupBy(w => w.OriginWord[0]).ToDictionary(g => g.Key, g => g.ToList()); var words2 = words.GroupBy(w => w.OriginWord[w.OriginWord.Length - 1]).ToDictionary(g => g.Key, g => g.ToList()); List <SymmetricGroup> symmetricGroups = words.Select(w => new SymmetricGroup(new Sentence(w), new Sentence(), new Difference(w.OriginWord))).ToList(); var differenceRoot1 = new DifferenceNode(); var differenceRoot2 = new DifferenceNode(); foreach (SymmetricGroup symmetricGroup in symmetricGroups) { differenceRoot1.Add(symmetricGroup.Difference, 0); } while (symmetricGroups.Any(x => x.Sentence.Length < MaxLength)) { result = GetPalindrom(symmetricGroups); if (result != NoAnswer) { return(result); } symmetricGroups = symmetricGroups.SelectMany(x => x.Join(words1, words2, differenceRoot1, differenceRoot2)).ToList(); if (!symmetricGroups.Any()) { return(NoAnswer); } } return(result); }
internal IEnumerable <SymmetricGroup> Join( Dictionary <char, List <Word> > words1, Dictionary <char, List <Word> > words2, DifferenceNode differenceRoot1, DifferenceNode differenceRoot2) { int len1 = Sentence.Length; int len2 = ReverseSentence.Length; if (len1 < len2) { List <Word> words; if (!words1.TryGetValue(Difference.CharAtFromEnd(0), out words)) { yield break; } foreach (Word word in words) { bool canJoin = true; int charCountToCheck = Math.Min(word.OriginWord.Length, len2 - len1); for (int i = 1; i < charCountToCheck; i++) { if (word.OriginWord[i] != Difference.CharAtFromEnd(i)) { canJoin = false; break; } } if (canJoin) { Difference newDifference; if (len2 - len1 >= word.OriginWord.Length) { string baseWord = ReverseSentence.Words.First.OriginWord; newDifference = new Difference(baseWord, 0, len2 - len1 - word.OriginWord.Length); if (!differenceRoot2.AddReverse(newDifference, 0)) { continue; } } else { newDifference = new Difference(word.OriginWord, len2 - len1, word.OriginWord.Length - len2 + len1); if (!differenceRoot1.Add(newDifference, 0)) { continue; } } yield return(new SymmetricGroup(Sentence.Append(word), ReverseSentence, newDifference)); } } } if (len1 > len2) { List <Word> words; if (!words2.TryGetValue(Difference.CharAt(0), out words)) { yield break; } foreach (Word word in words) { bool canJoin = true; int charCountToCheck = Math.Min(word.OriginWord.Length, len1 - len2); for (int i = 1; i < charCountToCheck; i++) { if (word.OriginWord[word.OriginWord.Length - 1 - i] != Difference.CharAt(i)) { canJoin = false; break; } } if (canJoin) { Difference newDifference; if (len1 - len2 >= word.OriginWord.Length) { string baseWord = Sentence.Words.Last.OriginWord; newDifference = new Difference(baseWord, baseWord.Length - len1 + len2 + word.OriginWord.Length, len1 - len2 - word.OriginWord.Length); if (!differenceRoot1.Add(newDifference, 0)) { continue; } } else { newDifference = new Difference(word.OriginWord, 0, word.OriginWord.Length - len1 + len2); if (!differenceRoot2.AddReverse(newDifference, 0)) { continue; } } yield return(new SymmetricGroup(Sentence, ReverseSentence.Prepend(word), newDifference)); } } } }