Próbuję rozwiązać problem, który jest prawie dokładnie taki. W szczególności dostaję ciąg s
taki, że s.Length % 4 == 0
i każdy s[i]
jest jednym z 'A'
, 'C'
, 'T'
lub 'G'
. Chcę znaleźć najmniejszy podciąg, który można zastąpić, aby każdy z nich był wyświetlany dokładnie jeden raz.Najmniejszy podłańcuch, który można zastąpić, aby ciąg zawierał taką samą liczbę znaków.
Na przykład z s="GAAATAAA"
, jednym optymalnym rozwiązaniem jest zastąpienie podłańcucha "AAATA"
przez "TTCCG"
, co daje "GTTCCGAA"
.
Opisałem moje podejście w komentarzach poniżej i zastanawiam się, czy jest on całkowicie poprawny, ponieważ doprowadzi mnie do prawidłowej odpowiedzi.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
class Solution
{
static string ReplacementForSteadiness(string s)
{
var counter = new Dictionary<char,int>() {
{ 'A', 0 }, { 'C', 0 }, { 'G', 0 }, { 'T', 0 }
};
for(int i = 0; i < s.Length; ++i)
counter[s[i]] += 1;
int div = s.Length/4;
var pairs = counter.ToList();
if(pairs.All(p => p.Value == div))
return "";
// If here, that means there is an even count of characters in s. For example, if
// s = "AAATGTTCTTGCGGGG", then counter = { A -> 3, T -> 5, C -> 2, G -> 6 },
// div = 4, and we know that we need to increase the number of As by 1, decrease
// the number of Ts by 1, increase the number of Cs by 2 and decrease the number
// of Gs by 2.
// The smallest strings to replace will have 1 T and 2 Gs, to be replaced with 1 A and
// 2 Cs (The order of characters in the replacement string doesn't matter).
// "TGG" --> "ACC"
// "GTG" --> "ACC"
// "GGT" --> "ACC"
// None of those strings exist in s. The next smallest strings that could be replaced
// would have 1 T and 3Gs, to be replaced with 1 A and 2 of the Gs to be replaced with
// Cs. Or, 2 Ts and 2Gs, 1 of the Ts to be replaced by an A and both the Gs to be replaced
// by Cs.
// "TGGG" --> "AGCC"
// "GTGG" --> "AGCC"
// "GGTG" --> "AGCC"
// "GGGT" --> "AGCC"
// "TTGG" --> "ATCC"
// "TGTG" --> "ATCC"
// "GTGT" --> "ATCC"
// "GGTT" --> "ATCC"
// None of those strings exist in s. Etc.
string r;
// ...
return r;
}
static void Main(String[] args)
{
Console.ReadLine(); // n
string str = Console.ReadLine();
string replacement = ReplacementForSteadiness(str);
Console.WriteLine(replacement.Length);
}
}
Czy można założyć, że istnieje rozwiązanie? Na przykład.ciąg 'AAB' nie może być edytowany na łańcuch zawierający tę samą liczbę liter" A "i" B "- czy masz gwarancję, że takie przypadki nie będą miały miejsca? –
@j_random_hacker: długość musi być podzielna przez 4, uważam, że powinna wystarczyć. Wydaje się również, że nie trzeba zastępować wszystkich liter w tym podciągu (z tego komentarza: '" GGTG "->" AGCC "', gdzie 'G' na drugim indeksie się nie zmienia). – Groo
To podejście niestety zajmie co najmniej wykładniczy czas w najgorszym przypadku, ponieważ potrzebny podłańcuch może mieć długość O (n) (np. Jeśli twój przykład został zmieniony tak, że wszystkie 'T' były z przodu i wszystkie 'G's na końcu, tak aby O (n)' C's i 'A' pojawiły się pomiędzy dowolnym' T' i 'G'), i (wydaje się), że generujesz i testujesz wszystkie prawidłowe podłańcuchy w rosnącym kolejność długości. –