lcs.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use crate::{patch::OpMethod, util::str_to_chars};
  19. pub struct Lcs<'a> {
  20. a: Vec<&'a str>,
  21. b: Vec<&'a str>,
  22. lengths: Vec<Vec<u64>>,
  23. }
  24. impl<'a> Lcs<'a> {
  25. pub fn new(a: &'a str, b: &'a str) -> Self {
  26. let a: Vec<_> = str_to_chars(a);
  27. let b: Vec<_> = str_to_chars(b);
  28. let (na, nb) = (a.len(), b.len());
  29. let mut lengths = vec![vec![0; nb + 1]; na + 1];
  30. for (i, ci) in a.iter().enumerate() {
  31. for (j, cj) in b.iter().enumerate() {
  32. lengths[i + 1][j + 1] = if ci == cj {
  33. lengths[i][j] + 1
  34. } else {
  35. lengths[i][j + 1].max(lengths[i + 1][j])
  36. }
  37. }
  38. }
  39. Self { a, b, lengths }
  40. }
  41. fn op(&self, ops: &mut Vec<OpMethod>, i: usize, j: usize) {
  42. if i == 0 && j == 0 {
  43. return
  44. }
  45. if i == 0 {
  46. ops.push(OpMethod::Insert(self.b[j - 1].to_string()));
  47. self.op(ops, i, j - 1);
  48. } else if j == 0 {
  49. ops.push(OpMethod::Delete((1) as _));
  50. self.op(ops, i - 1, j);
  51. } else if self.a[i - 1] == self.b[j - 1] {
  52. ops.push(OpMethod::Retain((1) as _));
  53. self.op(ops, i - 1, j - 1);
  54. } else if self.lengths[i - 1][j] > self.lengths[i][j - 1] {
  55. ops.push(OpMethod::Delete((1) as _));
  56. self.op(ops, i - 1, j);
  57. } else {
  58. ops.push(OpMethod::Insert(self.b[j - 1].to_string()));
  59. self.op(ops, i, j - 1);
  60. }
  61. }
  62. pub fn ops(&self) -> Vec<OpMethod> {
  63. let mut ops = vec![];
  64. self.op(&mut ops, self.a.len(), self.b.len());
  65. ops.reverse();
  66. ops
  67. }
  68. }
  69. #[cfg(test)]
  70. mod tests {
  71. use super::*;
  72. #[test]
  73. fn test_lcs() {
  74. let lcs = Lcs::new("hello", "test hello");
  75. assert_eq!(
  76. lcs.ops(),
  77. vec![
  78. OpMethod::Insert("t".into()),
  79. OpMethod::Insert("e".into()),
  80. OpMethod::Insert("s".into()),
  81. OpMethod::Insert("t".into()),
  82. OpMethod::Insert(" ".into()),
  83. OpMethod::Retain(1),
  84. OpMethod::Retain(1),
  85. OpMethod::Retain(1),
  86. OpMethod::Retain(1),
  87. OpMethod::Retain(1),
  88. ]
  89. );
  90. let lcs = Lcs::new("hello world", "hello");
  91. assert_eq!(
  92. lcs.ops(),
  93. vec![
  94. OpMethod::Retain(1),
  95. OpMethod::Retain(1),
  96. OpMethod::Retain(1),
  97. OpMethod::Retain(1),
  98. OpMethod::Delete(1),
  99. OpMethod::Delete(1),
  100. OpMethod::Delete(1),
  101. OpMethod::Retain(1),
  102. OpMethod::Delete(1),
  103. OpMethod::Delete(1),
  104. OpMethod::Delete(1),
  105. ]
  106. );
  107. }
  108. }