Esse desafio é escrever código para resolver o seguinte problema.
Dadas duas seqüências A e B, seu código deve gerar os índices inicial e final de uma subseqüência de caracteres A com as seguintes propriedades.
- A substring de A também deve corresponder a alguma substring de B com até uma substituição de um único caractere na string.
- Não deve mais haver substring de A que satisfaça a primeira propriedade.
Por exemplo:
A = xxxappleyyyyyyy
B = zapllezzz
A substring apple
com índices 4 8
(indexação de 1) seria uma saída válida.
Ponto
A pontuação da sua resposta será a soma do comprimento do seu código em bytes + o tempo em segundos que leva no meu computador quando executado nas cadeias A e B de 1 milhão de comprimento cada.
Teste e entrada
Executarei seu código em duas cadeias de comprimento 1 milhão extraídas das cadeias em http://hgdownload.cse.ucsc.edu/goldenPath/hg38/chromosomes/
A entrada será no padrão e será simplesmente duas strings, separadas por uma nova linha.
Línguas e bibliotecas
Você pode usar qualquer idioma que tenha um compilador / intérprete disponível gratuitamente / etc. para Linux e quaisquer bibliotecas também de código aberto e disponíveis gratuitamente para Linux.
Minha máquina Os horários serão executados na minha máquina. Esta é uma instalação padrão do ubuntu em um processador AMD FX-8350 de oito núcleos. Isso também significa que eu preciso poder executar seu código. Como conseqüência, use apenas software livre facilmente disponível e inclua instruções completas sobre como compilar e executar seu código.
fonte
if(hash(str1 == test1 && str2 == test2)) print("100,150") else ..
-- pensamentos?appley
precisa de duas substituições para combinarapllez
. Talvez você tenha perdido que estáapll
em B e nãoappl
?Respostas:
Tempo C ++: O (n ^ 2), espaço extra: O (1)
Demora 0,2s para concluir os dados de 15K na minha máquina.
Para compilá-lo, use:
Para executá-lo, use:
Explicação
A ideia é simples, para string
s1
es2
, tentamos compensars2
pori
:Quando o deslocamento é 3:
Em seguida, para cada deslocamento
i
, realizamos uma verificação dinâmica de programação ems1[i:]
es2
. Para cada umj
,f[j, 0]
seja o comprimento máximod
tal ques1[j - d:j] == s2[j - i - d: j - i]
. Da mesma forma,f[j, 1]
seja o comprimento máximod
tal que as stringss1[j - d:j]
es2[j - i - d:j - i]
diferam no máximo 1 caractere.Então
s1[j] == s2[j - i]
, temos:De outra forma:
E:
Como precisamos apenas de f [j - 1,:] para calcular f [j,:], apenas O (1) espaço extra é usado.
Por fim, o comprimento máximo será:
Código
fonte
C ++
Tentei pensar em um bom algoritmo para fazer isso, mas hoje estou um pouco distraído e não consegui pensar em nada que funcionaria bem. Isso é executado no horário O (n ^ 3), portanto é muito lento. A outra opção em que pensei poderia ter sido teoricamente mais rápida, mas ocuparia espaço O (n ^ 2) e, com entradas de 1M, teria sido ainda pior.
É vergonhoso, leva 190 segundos para entradas de 15K. Vou tentar melhorar. Edit: Adicionado multiprocessamento. Agora leva 37 segundos para entrada de 15K em 8 threads.
fonte
i < a.length()
parai < a.length - (longestA.second - longestA.first)
(o mesmo para j e b.length ()), pois não será necessário processar nenhuma correspondência menor que a atual mais longaR
Parece que eu estava complicando demais o problema com a solução anterior. Isso é cerca de 50% mais rápido (23 segundos em 15k strings) do que o anterior e bastante simples.
Isso nunca será um candidato devido ao idioma, mas eu me diverti um pouco fazendo isso.
Não tenho certeza da complexidade, mas em algumas cordas de ~ 15k são necessários 43 segundos usando um único encadeamento. A maior parte disso foi a classificação das matrizes. Eu tentei algumas outras bibliotecas, mas sem melhorias significativas.
Método:
fonte