字符串编辑距离
要想把字符串S1變成S2,可以經過若干次下列原子操作:
1.刪除一個字符
2.增加一個字符
3.更改一個字符
字符串S1和S2的編輯距離定義為從S1變成S2所需要原子操作的最少次數。
解法跟上面的最長公共子序列十分相似,都是動態規劃,把一個問題轉換為若干個規模更小的子問題,并且都借助于一個二維矩陣來實現計算。
約定:字符串S去掉最后一個字符T后為S',T1和T2分別是S1和S2的最后一個字符。
則dist(S1,S2)是下列4個值的最小者:
1.dist(S1',S2')--當T1==T2
2.1+dist(S1',S2)--當T1!=T2,并且刪除S1的最后一個字符T1
3.1+dist(S1,S2')--當T1!=T2,并且在S1后面增加一個字符T2
4.1+dist(S1',S2')--當T1!=T2,并且把S1的最的一個字符T1改成T2
把問題轉換為二維矩陣:
arr[i][j]表示S1.sub(0,i)和S2.sub(0,j)的編輯距離,則
arr[i][j]=min{1+arr[i][j-1], 1+arr[i-1][j], 1+arr[i-1][j-1](當S1[i]!=S2[j]), arr[i-1][j-1](當S1[i]==S2[j])}
邊界情況:arr[0][j]=j, arr[i][0]=i
首先定義這樣一個函數——edit(i, j),它表示第一個字符串的長度為i的子串到第二個字符串的長度為j的子串的編輯距離。
顯然可以有如下動態規劃公式:
- if i == 0 且 j == 0,edit(i, j) = 0
- if i == 0 且 j > 0,edit(i, j) = j
- if i > 0 且j == 0,edit(i, j) = i
- if?i ≥ 1? 且?j ≥ 1 ,edit(i, j) == min{ edit(i-1, j) + 1, edit(i, j-1) + 1, edit(i-1, j-1) + f(i, j) },當第一個字符串的第i個字符不等于第二個字符串的第j個字符時,f(i, j) = 1;否則,f(i, j) = 0。
?
?
| ? | 0 | f | a | i | l | i | n | g |
| 0 | ? | ? | ? | ? | ? | ? | ? | ? |
| s | ? | ? | ? | ? | ? | ? | ? | ? |
| a | ? | ? | ? | ? | ? | ? | ? | ? |
| i | ? | ? | ? | ? | ? | ? | ? | ? |
| l | ? | ? | ? | ? | ? | ? | ? | ? |
| n | ? | ? | ? | ? | ? | ? | ? | ? |
?
?
| ? | 0 | f | a | i | l | i | n | g |
| 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| s | 1 | ? | ? | ? | ? | ? | ? | ? |
| a | 2 | ? | ? | ? | ? | ? | ? | ? |
| i | 3 | ? | ? | ? | ? | ? | ? | ? |
| l | 4 | ? | ? | ? | ? | ? | ? | ? |
| n | 5 | ? | ? | ? | ? | ? | ? | ? |
?計算edit(1, 1),edit(0, 1) + 1 == 2,edit(1, 0) + 1 == 2,edit(0, 0) + f(1, 1) == 0 + 1 == 1,min(edit(0, 1),edit(1, 0),edit(0, 0) + f(1, 1))==1,因此edit(1, 1) == 1。 依次類推:
| ? | 0 | f | a | i | l | i | n | g |
| 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| s | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| a | 2 | 2 | ? | ? | ? | ? | ? | ? |
| i | 3 | ? | ? | ? | ? | ? | ? | ? |
| l | 4 | ? | ? | ? | ? | ? | ? | ? |
| n | 5 | ? | ? | ? | ? | ? | ? | ? |
edit(2, 1) + 1 == 3,edit(1, 2) + 1 == 3,edit(1, 1) + f(2, 2) == 1 + 0 == 1,其中s1[2] == 'a' 而 s2[1] == 'f'‘,兩者不相同,所以交換相鄰字符的操作不計入比較最小數中計算。以此計算,得出最后矩陣為:
| ? | 0 | f | a | i | l | i | n | g |
| 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| s | 1 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| a | 2 | 2 | 1 | 2 | 3 | 4 | 5 | 6 |
| i | 3 | 3 | 2 | 1 | 2 | 3 | 4 | 5 |
| l | 4 | 4 | 3 | 2 | 1 | 2 | 3 | 4 |
| n | 5 | 5 | 4 | 3 | 2 | 2 | 2 | 3 |
總結
- 上一篇: 统计0到n之间1的个数
- 下一篇: 字符流中第一个不重复的字符