Masalahnya menjadi lebih mudah, jika kita mempertimbangkan penghapusan panjang dan penyalinan substring alih-alih transposisi. Asumsikan bahwa kita menggunakan algoritma pemrograman dinamis standar untuk perhitungan mengedit jarak, dan bahwa operasi yang mahal panjang meningkatkan jarak dengan sebuah k + b , untuk beberapa konstanta a , b ≥ 0 . Konstanta ini mungkin berbeda untuk penghapusan panjang dan penyalinan substring.kak+ba,b≥0
Penghapusan panjang adalah penghapusan substring sewenang-wenang dari . Mendukung mereka itu mudah, jika kita memecahnya menjadi dua jenis operasi sederhana: menghapus karakter pertama (biaya a + b ) dan memperluas penghapusan dengan satu karakter (biaya a ). Selain array standar A , di mana A [ i , j ] adalah jarak edit antara awalan x [ 1 ... i ] dan y [ 1 ... j ] , kami menggunakan array lain A dxa+baAA[i,j]x[1…i]y[1…j]Aduntuk menyimpan jarak edit, saat operasi terakhir yang digunakan adalah penghapusan yang panjang. Dengan larik ini, kita hanya perlu melihat , A [ i - 1 , j - 1 ] , A [ i , j - 1 ] dan A d [ i - 1 , j ] saat menghitung A [ i , j ] dan A d [ iA[i−1,j]A[i−1,j−1]A[i,j−1]Ad[i−1,j]A[i,j] , memungkinkan kita untuk melakukannya dalam O ( 1 ) waktu.Ad[i,j]O(1)
Penyalinan substring berarti penyisipan substring sewenang-wenang dari ke string yang diedit. Seperti dengan penghapusan panjang, kami memecah operasi menjadi dua operasi sederhana: memasukkan karakter pertama dan memperluas penyisipan dengan satu karakter. Kami juga menggunakan berbagai A s untuk menyimpan mengedit jarak antara prefiks, asalkan operasi terakhir yang digunakan adalah substring menyalin.xAs
Melakukan ini secara efisien lebih rumit daripada dengan penghapusan yang lama, dan saya tidak yakin apakah kita bisa mengamortisasi waktu per sel. Kami membangun pohon akhiran untuk x , yang membutuhkan waktu O ( | x | ) , dengan asumsi alfabet ukuran konstan. Kami menyimpan pointer ke simpul pohon akhiran saat ini dalam A s [ i , j - 1 ] , memungkinkan kami untuk memeriksa dalam waktu yang konstan, apakah kami dapat memperluas penyisipan dengan karakter y [ j ] . Jika itu benar, kita dapat menghitung A [ iO(1)xO(|x|)As[i,j−1]y[j] dan A s [ i , j ] dalam waktu konstan.A[i,j]As[i,j]
Jika tidak, , di mana z adalah substring yang dimasukkan yang digunakan untuk menghitung A s [ i , j - 1 ] , bukan substring dari x . Kami menggunakan pohon sufiks untuk menemukan sufiks terpanjang z ′ dari z , yang z ′ y [ j ] adalah substring dari x , dalam waktu O ( | z | - | z ′ | ) . Untuk menghitungzy[j]zAs[i,j−1]xz′zz′y[j]xO(|z|−|z′|) , kita sekarang perlu melihat sel A [ i , j - | z ′ | - 1 ] hingga A [ i , j - 1 ] . Menemukan akhiran z ′ hanya membutuhkan waktu diamortisasi O ( 1 ) per sel, tetapi menghitung A s [ i , j ] dengan pendekatan brute-force membutuhkan O ( | zAs[i,j]A[i,j−|z′|−1]A[i,j−1]z′O(1)As[i,j] waktu. Mungkin ada beberapa cara untuk melakukan ini dengan lebih efisien, tetapi saya tidak dapat menemukannya sekarang.O(|z′|)
Dalam kasus terburuk, algoritma membutuhkan waktu , tetapi analisis yang lebih baik harus dimungkinkan. Jarak edit yang dihasilkan dengan penghapusan panjang dan penyalinan substring tidak simetris, tetapi itu seharusnya tidak menjadi masalah. Setelah semua, biasanya lebih mudah untuk mencapai string kosong dari yang kosong daripada sebaliknya.O(min(|x|⋅|y|2,|x|2⋅|y|))