题目来源
问题描述
DNA 是由 ACGT 四种核苷酸组成,例如 AAAGTCTGAC,假定自然环境下 DNA 发生异变的情况有:
- 基因缺失一个核苷酸
- 基因新增一个核苷酸
- 基因替换一个核苷酸
且发生概率相同。
古生物学家 Sam 得到了若干条相似 DNA 序列,Sam 认为一个 DNA 序列向另外一个 DNA 序列转变所需的最小异变情况数可以代表其物种血缘相近程度,异变情况数越少,血缘越相近,请帮助 Sam 实现获取两条 DNA 序列的最小异变情况数的算法。
解法
直接使用二维DP操作,有两种操作,如果字符相等,等于上一个状态,如果不相等,看一下是替换?还是删除,删除的情况分成两种,如图所示:
定义dp[i][j] 表示 dna1 中前 i 个字符变成 dna2 中前j个字符最少需要多少步。
容易从图中看出相应的状态转移。
//dp[i][j] 表示 dna1 中前 i 个字符变成 dna2 中前j个字符最少需要多少步
package main
import (
"fmt"
"strings"
)
func main() {
var s string
fmt.Scan(&s)
s11 := strings.Split(s, ",")
s1 := s11[0]
s2 := s11[1]
dp := make([][]int, len(s1)+1)
for i:=0;i<=len(s1);i++{
dp[i] = make([]int, len(s2)+1)
}
for i:=1;i<=len(s1);i++{
dp[i][0] = i
}
for i:=1;i<=len(s2);i++{
dp[0][i] = i
}
for i :=1;i<=len(s1);i++{
for j:=1;j<=len(s2);j++{
if s1[i-1] == s2[j-1]{
//相等,不变
dp[i][j] = dp[i-1][j-1]
}else{
//不相等,根据题目的意思有三种思路.
dp[i][j] = min(dp[i-1][j-1] + 1, dp[i][j-1]+1)
dp[i][j] = min(dp[i][j], dp[i-1][j] + 1)
}
}
}
fmt.Print(dp[len(s1)][len(s2)])
}
func min(x, y int) int{
if x > y{
return y
}
return x
}