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] Tính FIRST của chuỗi ký hiệu

    Trong quá trình xây dựng bảng phân tích LR (đặc biệt là bước tính tập lookahead cho các mục LR(1) khi đóng tập item), người ta thường xuyên cần tính FIRST(α)FIRST(\alpha)FIRST(α) của một chuỗi ký hiệu văn phạm α=X1X2…Xk\alpha = X_1 X_2 \ldots X_kα=X1​X2​…Xk​, dựa trên các tập FIRSTFIRSTFIRST của từng ký hiệu đã được tính sẵn (giả thiết đã đúng, không cần tính lại từ đầu bằng thuật toán điểm bất động).

    Quy tắc chuẩn:

    • FIRST(ε)={ε}FIRST(\varepsilon) = \{\varepsilon\}FIRST(ε)={ε} (chuỗi rỗng, k=0k = 0k=0).
    • FIRST(X1X2…Xk)FIRST(X_1 X_2 \ldots X_k)FIRST(X1​X2​…Xk​): duyệt lần lượt X1,X2,…X_1, X_2, \ldotsX1​,X2​,…; với mỗi XiX_iXi​, thêm FIRST(Xi)∖{ε}FIRST(X_i) \setminus \{\varepsilon\}FIRST(Xi​)∖{ε} vào kết quả; nếu ε∉FIRST(Xi)\varepsilon \notin FIRST(X_i)ε∈/FIRST(Xi​) thì dừng lại ngay (không xét các ký hiệu sau); nếu duyệt hết toàn bộ kkk ký hiệu mà ký hiệu nào cũng có ε\varepsilonε trong tập FIRST của nó (tức toàn bộ chuỗi có thể dẫn xuất ra rỗng) thì thêm ε\varepsilonε vào kết quả.
    • Một ký hiệu là kết thúc (terminal) nếu nó không xuất hiện trong danh sách phi kết thúc cho trước; khi đó FIRSTFIRSTFIRST của nó chỉ gồm chính nó và không chứa ε\varepsilonε.

    Ví dụ: Cho FIRST(A)={a,ε}FIRST(A) = \{a, \varepsilon\}FIRST(A)={a,ε}, FIRST(B)={b}FIRST(B) = \{b\}FIRST(B)={b}. Với chuỗi α=A B\alpha = A\,Bα=AB: FIRST(A)∖{ε}={a}FIRST(A) \setminus \{\varepsilon\} = \{a\}FIRST(A)∖{ε}={a} được thêm vào; vì ε∈FIRST(A)\varepsilon \in FIRST(A)ε∈FIRST(A) nên xét tiếp BBB: thêm {b}\{b\}{b}; BBB không có ε\varepsilonε nên dừng. Kết quả: FIRST(α)={a,b}FIRST(\alpha) = \{a, b\}FIRST(α)={a,b}, không chứa ε\varepsilonε.

    Hãy viết chương trình tính FIRST(α)FIRST(\alpha)FIRST(α) theo đúng quy tắc trên.

    • Định dạng đầu vào:
      • Dòng 1: số nguyên nnn (0≤n≤1000 \le n \le 1000≤n≤100) — số ký hiệu phi kết thúc có tập FIRST cho trước.
      • nnn dòng tiếp theo, mỗi dòng có dạng TÊN: t1 t2 ... tm, trong đó TÊN là tên ký hiệu phi kết thúc (theo sau là dấu hai chấm dính liền, không có khoảng trắng trước dấu :), và t1 t2 ... tm là các phần tử của FIRSTFIRSTFIRST(TÊN) cách nhau bởi khoảng trắng. Token đặc biệt EPS (nếu xuất hiện trong danh sách) biểu diễn ε∈FIRST\varepsilon \in FIRSTε∈FIRST(TÊN). Các phần tử còn lại là tên ký hiệu kết thúc.
      • Dòng tiếp theo: số nguyên kkk (0≤k≤10000 \le k \le 10000≤k≤1000) — độ dài chuỗi α\alphaα.
      • Dòng tiếp theo: nếu k>0k > 0k>0, gồm kkk ký hiệu X1…XkX_1 \ldots X_kX1​…Xk​ cách nhau bởi khoảng trắng (mỗi ký hiệu hoặc là một trong nnn tên phi kết thúc ở trên, hoặc là một ký hiệu kết thúc bất kỳ — không nhất thiết đã xuất hiện ở đâu trước đó); nếu k=0k = 0k=0, đây là một dòng trống.
    • Định dạng đầu ra:

      In ra đúng 2 dòng:

      • Dòng 1: các ký hiệu kết thúc thuộc FIRST(α)FIRST(\alpha)FIRST(α), liệt kê theo thứ tự tăng dần của so sánh chuỗi (thứ tự từ điển theo mã ASCII), cách nhau bởi dấu phẩy , (không có khoảng trắng). Nếu tập rỗng, in ra dấu -.
      • Dòng 2: EPS: YES nếu ε∈FIRST(α)\varepsilon \in FIRST(\alpha)ε∈FIRST(α), ngược lại in EPS: NO.

    Ví dụ:

    Đầu vào:

    2
    A: a
    B: b
    0
    
    

    Đầu ra:

    -
    EPS: YES
    

    Đầu vào:

    3
    A: a EPS
    B: b
    C: c EPS
    3
    A B C
    

    Đầu ra:

    a,b
    EPS: NO
    

    Đang tải editor...