Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Khoảng cách sửa lỗi tối thiểu giữa hai dãy token

    Một kỹ thuật phục hồi lỗi mạnh — sửa lỗi khoảng cách tối thiểu (minimum-distance error correction) — tìm dãy phép chèn (insert), xóa (delete), thay thế (substitute) token với số phép ít nhất để biến dãy token thực tế mà lexer đọc được thành dãy token mà văn phạm/parser mong đợi. Đây chính là khoảng cách chỉnh sửa Levenshtein trên dãy token (mỗi phép chi phí 1).

    Cho dãy token thực tế A=a1…anA = a_1 \ldots a_nA=a1​…an​ và dãy token kỳ vọng B=b1…bmB = b_1 \ldots b_mB=b1​…bm​. Gọi dp[i][j]dp[i][j]dp[i][j] là khoảng cách sửa lỗi tối thiểu giữa a1…aia_1\ldots a_ia1​…ai​ và b1…bjb_1 \ldots b_jb1​…bj​:

    dp[i][0]=i,dp[0][j]=jdp[i][0]=i,\quad dp[0][j]=jdp[i][0]=i,dp[0][j]=j dp[i][j]={dp[i−1][j−1]neˆˊu ai=bj1+min⁡(dp[i−1][j−1], dp[i−1][j], dp[i][j−1])neˆˊu ai≠bjdp[i][j] = \begin{cases} dp[i-1][j-1] & \text{nếu } a_i = b_j \\ 1+\min(dp[i-1][j-1],\ dp[i-1][j],\ dp[i][j-1]) & \text{nếu } a_i \ne b_j\end{cases}dp[i][j]={dp[i−1][j−1]1+min(dp[i−1][j−1], dp[i−1][j], dp[i][j−1])​neˆˊu ai​=bj​neˆˊu ai​=bj​​

    Vì có thể có nhiều cách phân rã tối ưu khác nhau (cùng tổng chi phí nhưng khác số lượng insert/delete/substitute), để kết quả xác định duy nhất, quy ước dựng lại đường đi từ (n,m)(n,m)(n,m) về (0,0)(0,0)(0,0): tại mỗi ô, áp dụng lựa chọn khả thi đầu tiên theo đúng thứ tự ưu tiên sau:

    1. Nếu ai=bja_i = b_jai​=bj​ và dp[i][j]=dp[i−1][j−1]dp[i][j]=dp[i-1][j-1]dp[i][j]=dp[i−1][j−1]: giữ nguyên (không tính là phép sửa), lùi về (i−1,j−1)(i-1,j-1)(i−1,j−1).
    2. Ngược lại, nếu dp[i][j]=dp[i−1][j−1]+1dp[i][j] = dp[i-1][j-1]+1dp[i][j]=dp[i−1][j−1]+1: tính là thay thế (substitute), lùi về (i−1,j−1)(i-1,j-1)(i−1,j−1).
    3. Ngược lại, nếu dp[i][j]=dp[i−1][j]+1dp[i][j] = dp[i-1][j]+1dp[i][j]=dp[i−1][j]+1: tính là xóa (delete, khỏi AAA), lùi về (i−1,j)(i-1,j)(i−1,j).
    4. Ngược lại (khi đó bắt buộc dp[i][j]=dp[i][j−1]+1dp[i][j]=dp[i][j-1]+1dp[i][j]=dp[i][j−1]+1): tính là chèn (insert, vào AAA để khớp BBB), lùi về (i,j−1)(i,j-1)(i,j−1).

    Ví dụ: A=A=A= a b c, B=B=B= a x c. dp[3][3]=1dp[3][3]=1dp[3][3]=1 (thay b thành x). Kết quả: khoảng cách 111, insert=0=0=0, delete=0=0=0, substitute=1=1=1.

    • Định dạng đầu vào:
      • Dòng 1: số nguyên nnn (0≤n≤3000 \le n \le 3000≤n≤300).
      • Dòng 2: nnn token của AAA, cách nhau khoảng trắng (dòng rỗng nếu n=0n=0n=0).
      • Dòng 3: số nguyên mmm (0≤m≤3000 \le m \le 3000≤m≤300).
      • Dòng 4: mmm token của BBB, cách nhau khoảng trắng (dòng rỗng nếu m=0m=0m=0).
    • Định dạng đầu ra:

      In ra 2 dòng:

      • Dòng 1: khoảng cách sửa lỗi tối thiểu dp[n][m]dp[n][m]dp[n][m].
      • Dòng 2: đúng định dạng insert=I delete=D substitute=S với I,D,SI, D, SI,D,S là số phép chèn, xóa, thay thế xác định theo quy ước dựng đường đi ở trên.

    Ví dụ:

    Đầu vào:

    3
    a b c
    3
    a x c
    

    Đầu ra:

    1
    insert=0 delete=0 substitute=1
    

    Đầu vào:

    2
    a b
    3
    a b c
    

    Đầu ra:

    1
    insert=1 delete=0 substitute=0
    

    Đang tải editor...