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] Loại bỏ biểu thức con chung bằng đánh số giá trị

    Cho một đoạn mã ba địa chỉ (TAC) tuyến tính (không nhãn, không rẽ nhánh) gồm nnn lệnh liên tiếp, lệnh thứ iii luôn có đích là tit_iti​ (i=1,…,ni=1,\ldots,ni=1,…,n). Mỗi lệnh có dạng tK = A op B (op ∈{+,−,∗,/}\in \{+,-,*,/\}∈{+,−,∗,/}) hoặc dạng sao chép tK = A, trong đó A, B là biến gốc, hằng số, hoặc một tJ (J<KJ<KJ<K).

    Hãy tối ưu đoạn mã bằng kỹ thuật đánh số giá trị cục bộ (local value numbering) để loại bỏ các phép tính trùng lặp, theo đúng quy tắc sau. Gọi canon(x)canon(x)canon(x) là "giá trị canonical hiện tại" của xxx: với biến gốc/hằng số chưa từng được định nghĩa, canon(x)=xcanon(x)=xcanon(x)=x; với tit_iti​ đã xử lý, canon(ti)canon(t_i)canon(ti​) được xác định như dưới đây. Xử lý các lệnh theo thứ tự i=1,…,ni=1,\ldots,ni=1,…,n:

    • Lệnh sao chép tK = A: đặt canon(tK)=canon(A)canon(t_K) = canon(A)canon(tK​)=canon(A); dòng xuất ra là tK = canon(A).
    • Lệnh tính toán tK = A op B: gọi a=canon(A)a=canon(A)a=canon(A), b=canon(B)b=canon(B)b=canon(B). Nếu op là + hoặc * (giao hoán), khóa biểu thức là (op, aaa, bbb đã sắp xếp theo thứ tự từ điển); nếu op là - hoặc / (không giao hoán), khóa là (op, aaa, bbb) giữ nguyên thứ tự.
      • Nếu khóa này trùng với khóa của một lệnh tP (P<KP<KP<K) đã xử lý trước đó: đặt canon(tK)=canon(tP)canon(t_K)=canon(t_P)canon(tK​)=canon(tP​), dòng xuất ra thay bằng tK = canon(t_P), và tính là 1 lệnh bị loại bỏ.
      • Nếu khóa mới: đặt canon(tK)=tKcanon(t_K)=t_Kcanon(tK​)=tK​, ghi nhớ khóa này ứng với tKt_KtK​, dòng xuất ra là tK = a op b.

    Lưu ý canon(tP)canon(t_P)canon(tP​) luôn chính bằng tPt_PtP​ (vì lần đầu một khóa mới xuất hiện, canoncanoncanon của đích được đặt bằng chính tên đích đó).

    • Định dạng đầu vào:

      Dòng 1: số nguyên nnn (1≤n≤1001 \le n \le 1001≤n≤100). nnn dòng tiếp theo: lệnh thứ iii theo đúng định dạng tK = A op B hoặc tK = A như mô tả (các token cách nhau một khoảng trắng, dấu = có khoảng trắng hai bên).

    • Định dạng đầu ra:

      Dòng đầu tiên: số nguyên là tổng số lệnh bị loại bỏ (thay bằng lệnh sao chép). nnn dòng tiếp theo: đoạn mã đã được tối ưu, theo đúng thứ tự t1,…,tnt_1,\ldots,t_nt1​,…,tn​ và đúng định dạng nêu trên.

    Ví dụ:

    Đầu vào:

    5
    t1 = a + b
    t2 = c - d
    t3 = b + a
    t4 = d - c
    t5 = t1 + t3

    Đầu ra:

    1
    t1 = a + b
    t2 = c - d
    t3 = t1
    t4 = d - c
    t5 = t1 + t1
    

    Đầu vào:

    1
    t1 = x + y

    Đầu ra:

    0
    t1 = x + y
    

    Đang tải editor...