雜記 › 資源分享 › 《聲律啟蒙》《笠翁對韻》整檔餵進文本對比頁:公共 154 行、新增 665 刪除 401,而統計只給兩個數

《聲律啟蒙》《笠翁對韻》整檔餵進文本對比頁:公共 154 行、新增 665 刪除 401,而統計只給兩個數

兩份全文TXT整檔餵進文本對比頁:實測新增665刪除401、公共154行;守衛只在兩側都空時命中,同分取捨定出刪前增後,移動一行記成1刪1增,統計那行只有兩個數。

兩份 TXT 先對行數

起因很樸素:我手上有兩份 TXT,一份 555 段、一份 819 段。想看的不是內容,而是逐行對比頁在語料級輸入下給出的賬——公共行怎麼數、增刪按什麼先後、統計那行寫了幾個數。兩份文件只當字節與行的語料,正文不引句子。

語料的字節與段數

兩份都是站內已發布資源:《聲律啟蒙》26353 字節、9185 碼元、9183 碼點,555 段、非空 403、空行 152;《笠翁對韻》28903 字節、10211 碼元、10209 碼點,819 段、非空 671、空行 148;都無 CRLF、也無 BOM。碼元比碼點多 2,來自兩份各有 2 個增平面碼點。被測頁就是文本對比,模板 118 行、4487 字節、腳本 3 個函數。

整檔餵進去的三筆賬

兩份全文直接調 lineDiff:added 665、removed 401、equal 154、結果 1220 條,dp 表 556 × 820 = 455920 個單元格,規模代價舊文算過,這檔數本篇只登記。恆等式:555 減 154 得 401、819 減 154 得 665、555 加 819 減 154 得 1220;方向對調則增刪兩數互換,equal 與單元格數不變。

輸入檔位A 段B 段removedaddedequal結果條數
全文切段5558194016651541220
先去掉空行40367139766561068
兩檔各自自比555 與 819同左00555 與 819同左

兩檔 added 同為 665,差額只在 removed:A 側 152 個空行被吸收 148 個,剩 4 個進刪除賬,所以是 401;去空行那檔的 dp 表為 404 × 672 = 271488。耗時只說腳本層:本地腳本連調 5 輪得 113.9、139.5、120.5、122.7、117.6 ms,中位數 120.5 ms——它是單次函數調用的耗時,不是頁面回應。

守衛只在兩側都空時命中

doDiff() 裡兩側 join 後 trim、都成空串才 toast「請輸入要比較的文本」並 return:判據是合起來全空白,不是逐側。四條實測:

  • 兩側都空、或 A 側只有 3 個半角空格:命中後什麼都不改,統計與顯示停在上一輪。
  • 一側空、另一側 403 條非空語料行:照跑,統計給「新增 403 行,刪除 1 行」。
  • 把那 403 行挪到 A 側:鏡像的「新增 1 行,刪除 403 行」。
  • 一側空、另一側換成全 555 段:給「新增 554 行,刪除 0 行」。

關鍵在最後一條:空串切出 1 段,對面沒空行時它落成刪除 1 行;對面有 152 條空行時被 LCS 吸收、刪除歸 0,新增變成 554。

守衛命中|兩側都空 空對空 · 3 空格對空 → 原樣返回 一側空 × 403 條非空行 新增 403 · 刪除 1 403 條非空行 × 一側空 新增 1 · 刪除 403 一側空 × 全 555 段 新增 554 · 刪除 0 空行少的一檔貢獻 148 · 公共行 154 = 148 + 6

圖 1:守衛的兩檔與空行改賬。

同分取捨定出刪前增後

回溯條件寫成 dp[i][j-1] >= dp[i][j]:同分先進 added 分支、j 減 1;回溯從表尾往回走,末尾又有 reverse(),於是輸出流固定刪前增後:

  • a、b 對 b、a:得 removed a、equal b、added a;走完 doDiff 後 A 側是「- a、b、佔位」、B 側「佔位、b、+ a」。
  • old 對 new:removed 與 added 相鄰一對;a、b 對 a、c:equal、removed、added。
  • 1、2、3、4 對 3、4、1、2:removed 1、2,equal 3、4,added 1、2——公共段錨在 3 與 4。

另開上下文只把 >= 換成 >:同批樣本 4 組順序翻轉、塊互換把錨挪到 1 與 2,另有 1 組逐行一模一樣——只作對照紀錄。

移動一行:取 10 行、把第 2 行插到第 9 位,自比 0 增 0 刪,挪後 added 1、removed 1、equal 9、結果 11 條——代碼裡沒有移動檢測。

統計那行只有兩個數

頁面那行串逐字是 新增 ${added} 行,删除 ${removed} 行,抽出數字恰好 2 個,整檔成品「新增 665 行,刪除 401 行」;公共行數與 dp 終值的 LCS 長度都不進串。上方文案「統計概覽:顯示新增行數、刪除行數、修改行數」這半句與代碼衝突:按修改計數的分支要行類型不屬於 equal、removed、added 才進,而三處 push 的字面量恰是這三種,1220 條那檔的類型集合仍是三個;改一行裡幾個字元也是整行落進兩側——詞級那層本頁沒有(舊文登記過)。

結果行進 DOM 的方式與殘留

渲染逐條 createElement 配 textContent:每側 1220 個 div、兩側共 2440 個一次全進;容器 max-height 400px 加 overflow auto,對照實驗 scrollHeight 29328px 對 400px。本頁無轉義函數也無複製按鈕,模板裡 <button 命中 2 個;含尖括號、& 與引號的行原樣讀回,對側佔位是單個 U+00A0;「清空」只把顯示設回隱藏,兩側各殘留 2 行。

CRLF 分兩層,舊文那條只登記一句複核:字串層帶 \r 的行對不帶的是 1 刪 1 增;走 textarea 則回車歸一成換行,貼上去得 0 增 0 刪。尾隨 LF 另有一筆:切分各多出 1 個空段,對去尾 LF 版實測 equal 554、刪除 1、新增 0。

整檔對跑:555 段 × 819 段 equal 154 removed 401 added 665 結果 1220 條 · 兩側共 2440 個 div dp 455920 = 556 × 820 · 腳本層中位 120.5 ms

圖 2:整檔對跑的三筆賬。

公共行的三本賬與它們落在檔尾

公共行的口徑有三本賬:多重集下含空行 154 條,空行按少的一檔貢獻 148、非空只剩 6;按種類去重得 6 種、再去空串剩 5 種,28 碼元的分隔線兩側各出 2 次;同位置的口徑只有 25 行。這 6 條不在文件開頭而在尾部說明塊——前者第 544 至 553 行、後者第 808 至 817 行——字串本身不搬進正文。整檔 LCS 恰是 154、去空行檔 LCS 恰是 6;與多重集交集相等只因兩側先後一致,是巧合、不是恆等式。

常見問題

Q:一側什麼都不填,會被當成錯誤攔下來嗎?

不會,守衛要兩側合起來全空白才命中;一側空、另一側 403 條非空行照跑,給「新增 403 行,刪除 1 行」。

Q:只挪動了一行,為什麼刪與增各漲 1?

結果類型裡沒有移動這一項,lineDiff 只產出 equal、added、removed 三種,挪一行就記 added 1、removed 1。

Q:公共行 154 條,為什麼統計裡看不見?

統計串只有「新增 665 行,刪除 401 行」兩個數,公共行數與 LCS 長度都不進串。

資源說明

兩處資源連結只交代語料出處:兩部書在這裡只按字節與行計數,正文不引句子、不作內容層面的解釋,尾部那 6 條公共字串只作行計數登記。頁面沒有檔案輸入通道,整檔只能靠貼上。

📎 相關文章

《笠翁對韻》量出 21 個轉不出拼音的字:8026 鍵拼音表實測命中 7160、多音 232 次 2026-11-07 千字文有一千個不重字嗎:字數統計實測正文 996、真字 1000、去重 995 2026-11-05 120 回的「紅樓夢」整本貼進文本頻率統計,榜首為什麼是 59260 次的逗號 2026-11-04 SOS 只有 9 個音,整句字母表要 104 個音:摩斯碼的節奏怎麼算出來 2026-10-21 轉盤上寫「權重 30」是幾成機會?扇區角度、放回與不放回的兩種抽法 2026-10-21