index.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. "use strict";
  2. const peq = new Uint32Array(0x10000);
  3. const myers_32 = (a, b) => {
  4. const n = a.length;
  5. const m = b.length;
  6. const lst = 1 << (n - 1);
  7. let pv = -1;
  8. let mv = 0;
  9. let sc = n;
  10. let i = n;
  11. while (i--) {
  12. peq[a.charCodeAt(i)] |= 1 << i;
  13. }
  14. for (i = 0; i < m; i++) {
  15. let eq = peq[b.charCodeAt(i)];
  16. const xv = eq | mv;
  17. eq |= ((eq & pv) + pv) ^ pv;
  18. mv |= ~(eq | pv);
  19. pv &= eq;
  20. if (mv & lst) {
  21. sc++;
  22. }
  23. if (pv & lst) {
  24. sc--;
  25. }
  26. mv = (mv << 1) | 1;
  27. pv = (pv << 1) | ~(xv | mv);
  28. mv &= xv;
  29. }
  30. i = n;
  31. while (i--) {
  32. peq[a.charCodeAt(i)] = 0;
  33. }
  34. return sc;
  35. };
  36. const myers_x = (a, b) => {
  37. const n = a.length;
  38. const m = b.length;
  39. const mhc = [];
  40. const phc = [];
  41. const hsize = Math.ceil(n / 32);
  42. const vsize = Math.ceil(m / 32);
  43. let score = m;
  44. for (let i = 0; i < hsize; i++) {
  45. phc[i] = -1;
  46. mhc[i] = 0;
  47. }
  48. let j = 0;
  49. for (; j < vsize - 1; j++) {
  50. let mv = 0;
  51. let pv = -1;
  52. const start = j * 32;
  53. const end = Math.min(32, m) + start;
  54. for (let k = start; k < end; k++) {
  55. peq[b.charCodeAt(k)] |= 1 << k;
  56. }
  57. score = m;
  58. for (let i = 0; i < n; i++) {
  59. const eq = peq[a.charCodeAt(i)];
  60. const pb = (phc[(i / 32) | 0] >>> i) & 1;
  61. const mb = (mhc[(i / 32) | 0] >>> i) & 1;
  62. const xv = eq | mv;
  63. const xh = ((((eq | mb) & pv) + pv) ^ pv) | eq | mb;
  64. let ph = mv | ~(xh | pv);
  65. let mh = pv & xh;
  66. if ((ph >>> 31) ^ pb) {
  67. phc[(i / 32) | 0] ^= 1 << i;
  68. }
  69. if ((mh >>> 31) ^ mb) {
  70. mhc[(i / 32) | 0] ^= 1 << i;
  71. }
  72. ph = (ph << 1) | pb;
  73. mh = (mh << 1) | mb;
  74. pv = mh | ~(xv | ph);
  75. mv = ph & xv;
  76. }
  77. for (let k = start; k < end; k++) {
  78. peq[b.charCodeAt(k)] = 0;
  79. }
  80. }
  81. let mv = 0;
  82. let pv = -1;
  83. const start = j * 32;
  84. const end = Math.min(32, m - start) + start;
  85. for (let k = start; k < end; k++) {
  86. peq[b.charCodeAt(k)] |= 1 << k;
  87. }
  88. score = m;
  89. for (let i = 0; i < n; i++) {
  90. const eq = peq[a.charCodeAt(i)];
  91. const pb = (phc[(i / 32) | 0] >>> i) & 1;
  92. const mb = (mhc[(i / 32) | 0] >>> i) & 1;
  93. const xv = eq | mv;
  94. const xh = ((((eq | mb) & pv) + pv) ^ pv) | eq | mb;
  95. let ph = mv | ~(xh | pv);
  96. let mh = pv & xh;
  97. score += (ph >>> (m - 1)) & 1;
  98. score -= (mh >>> (m - 1)) & 1;
  99. if ((ph >>> 31) ^ pb) {
  100. phc[(i / 32) | 0] ^= 1 << i;
  101. }
  102. if ((mh >>> 31) ^ mb) {
  103. mhc[(i / 32) | 0] ^= 1 << i;
  104. }
  105. ph = (ph << 1) | pb;
  106. mh = (mh << 1) | mb;
  107. pv = mh | ~(xv | ph);
  108. mv = ph & xv;
  109. }
  110. for (let k = start; k < end; k++) {
  111. peq[b.charCodeAt(k)] = 0;
  112. }
  113. return score;
  114. };
  115. const distance = (a, b) => {
  116. if (a.length > b.length) {
  117. const tmp = b;
  118. b = a;
  119. a = tmp;
  120. }
  121. if (a.length === 0) {
  122. return b.length;
  123. }
  124. if (a.length <= 32) {
  125. return myers_32(a, b);
  126. }
  127. return myers_x(a, b);
  128. };
  129. const closest = (str, arr) => {
  130. let min_distance = Infinity;
  131. let min_index = 0;
  132. for (let i = 0; i < arr.length; i++) {
  133. const dist = distance(str, arr[i]);
  134. if (dist < min_distance) {
  135. min_distance = dist;
  136. min_index = i;
  137. }
  138. }
  139. return arr[min_index];
  140. };
  141. module.exports = {
  142. closest, distance
  143. }