Хоёр string-д хоёуланд нь байгаа хамгийн урт нийтлэг дэд дарааллыг (LCS) хоёр хэмжээст хүснэгтээр олно.
Эхлээд жижиг бодлого
s = "ABC", t = "ACB" хоёр string байна. Хоёуланд нь байгаа хамгийн урт дэд дараалал юу вэ? Үсэг алгасаж болно, харин дарааллыг нь сольж болохгүй.
"AB" нь s-д байна, t-д A-ийн дараа B бий. "AC" ч бас болно. "ABC" бол t-д C нь B-ээс өмнө байгаа тул болохгүй. Хариу 2.
Энгийн аргаас санаа руу
Энгийн арга бол s-ийн бүх дэд дарааллыг үүсгээд t-д байгаа эсэхийг шалгах. n үсэгтэй s-д 2ⁿ дэд дараалал бий.
Гол санаа: хоёр string-ийн сүүлийн үсгийг харна. Ижил бол тэр үсэг хариунд орно: dp[i][j] = dp[i - 1][j - 1] + 1. Өөр бол хоёулаа хариунд сүүлд нь орж чадахгүй, аль нэгийг нь хаяна: max(dp[i - 1][j], dp[i][j - 1]). Хүснэгтийг мөр мөрөөр бөглөнө.
Нэр томьёо ба тэмдэглэгээ
- dp[i][j]
- State: s-ийн эхний i үсэг ба t-ийн эхний j үсгийн хамгийн урт нийтлэг дэд дараалал.
- s[i - 1]
- s-ийн i дэх үсэг. String 0-ээс, хүснэгт 1-ээс эхэлдэг тул нэгийг хасна.
- дэд дараалал
- Үсэг алгасаж болно, дараалал нь хадгалагдана. Substring бол зэргэлдээ байх ёстой, энэ нь өөр.
- LCS
- Longest Common Subsequence, хамгийн урт нийтлэг дэд дараалал.
ABCBDA ба BDCABA хоёр string-д хоёуланд нь байгаа хамгийн урт дэд дарааллыг олъё. Үсэг алгасаж болно, харин дарааллыг нь сольж болохгүй. State: dp[i][j] нь s-ийн эхний i үсэг, t-ийн эхний j үсгийн хариу.
- Space тоглуулах
- ←→ алхам
- −+ хурд
- Бөглөж буй нүд
- Transition-д уншиж буй нүд
- Бөглөсөн
- 0: хоосон string
- Нийтлэг үсгүүд
Нийтлэг дэд дараалал
ABCBDA ба BDCABA хоёуланд нь байгаа хамгийн урт дэд дараалал юу вэ? Үсэг алгасаж болно, харин дарааллыг нь сольж болохгүй. Жишээ нь BDA хоёуланд нь бий.
Дараа нь юу болох вэ?
Оноо 0 / 00дараалсан зөв, хамгийн их 0
Animation нэг алхам дээр зогсоно. Дараа нь код юу хийх вэ? Таагаад оноо цуглуул! Нэвтрэх хэрэггүй, оноо чинь энэ төхөөрөмж дээр хадгалагдана.
Юунд хэрэгтэй вэ?
Хоёр string-ийг харьцуулдаг олимпиадын бодлогуудын суурь. ДНХ-ийн дараалал харьцуулах, хоёр файлын ялгааг олох программууд ийм аргаар ажилладаг. HackerRank дээрх "Common Child" бодлого яг энэ.
Яаж ажилладаг вэ?
1. State: dp[i][j] нь s-ийн эхний i үсэг ба t-ийн эхний j үсгийн хамгийн урт нийтлэг дэд дараалал. Мөр 0 ба багана 0 бүгд 0. 2. s[i − 1] = t[j − 1] бол: dp[i][j] = dp[i − 1][j − 1] + 1. 3. Өөр бол аль нэг үсгийг хаяна: dp[i][j] = max(dp[i − 1][j], dp[i][j − 1]). 4. Хариу нь dp[n][m]. Оролт: хоёр мөрөнд s ба t string.
Яагаад зөв, хэр хурдан бэ?
Сүүлийн хоёр үсэг ижил бол тэдгээрийг хослуулахаас алдах юм байхгүй, үлдсэн хэсэг нь dp[i - 1][j - 1]. Өөр бол хамгийн сайн хариунд s-ийн сүүлийн үсэг эсвэл t-ийн сүүлийн үсэг ашиглагдахгүй. Тиймээс хоёр сонголтын их нь зөв.
n · m нүд, тус бүрийг O(1)-д бодно: хугацаа ба санах ой O(n · m). n = m = 1000 бол сая нүд. n = m = 5000 бол 25 сая нүд, хугацаа хүрэлцэнэ, харин int хүснэгт 100 MB орчим болно.
Түгээмэл алдаа
- String-ийн index-ийг хүснэгтийнхтэй андуурах.
dp[i][j]-дs[i - 1],t[j - 1]-ийг харьцуулна. - Substring-тэй андуурах. Энэ код зэргэлдээ байх албагүй дэд дараалал олно.
- Хүснэгтийг local хувьсагч болгох.
dp[1005][1005]main дотор stack-ийг дүүргэж болно, global болго.
Хязгаарын тохиолдол
- Нийтлэг үсэг огт байхгүй: бүх нүд 0, хариу 0.
- Хоёр string ижил: хариу нь string-ийн урт.
- Нэг нь нөгөөгийнхөө дэд дараалал: хариу нь богино string-ийн урт.
Өөрийгөө шалга
"HELLO" ба "YELLOW"-ийн LCS хэд вэ?
Хариу харах
4: ELLO.
"ABC" ба "XYZ"-ийн хариу хэд вэ?
Хариу харах
0.
Хоёр үсэг ижил үед аль нүдийг уншдаг вэ?
Хариу харах
Зүүн дээд нүд
dp[i - 1][j - 1]-ийг уншаад 1 нэмнэ.
Гурван дадлага
Hint-ээ нээхээс өмнө өөрөө оролдоорой.
1."AXBY" ба "ABXY"-ийн хүснэгтийг бөглөөд хариуг ол.
Hint харах
4×4 хүснэгт, мөр 0 ба багана 0 нь 0.
Хариу ба тайлбар
Хариу 3, жишээ нь AXY эсвэл ABY.
2.Уртыг нь биш, LCS-ийг өөрийг нь хэвлэдэг болго.
Hint харах
dp[n][m]-ээс эхлээд хүснэгтээр буцаж алх.Хариу ба тайлбар
i, j > 0 үед: үсэг ижил бол тэр үсгийг хадгалаад
i--, j--. Өөр болdp[i - 1][j] >= dp[i][j - 1]үедi--, үгүй болj--. Хадгалсан үсгүүдийг урвуу дарааллаар хэвлэнэ.3.String-ийн хамгийн урт palindrome дэд дарааллыг LCS-ээр ол.
Hint харах
Palindrome урдаасаа ч, ардаасаа ч ижил уншигдана.
Хариу ба тайлбар
Хариу нь
LCS(s, reverse(s)). "BBABCBCAB" бол 7, жишээ нь BABCBAB.
Жишээ
Оролт
ABCBDA BDCABA
Гаралт
4
Одоо өөрөө бодоод үз
Бодлого
Хичээл
Энэ сэдвийн хичээл удахгүй нэмэгдэнэ.