Tôi là Đức, xin chào các fan hâm mộ
Bài này chỉ cần để ý như sau:
Có 2 loại statement:
- Loại 1 kết thúc bởi dấu ;
- Loại 2 không kết thúc bởi dấu ; là các statement khai báo hàm, lặp, điều khiển blah blah.
Giả sử ta có 1 code block gồm cả loại 1 và loại 2, thấy rằng với loại 1 ta chỉ việc in ra theo indent là 2 (hoặc 4) còn loại 2 thì tự nó sẽ tạo ra 1 code block mới với indent = indent trước đó + 2 hoặc 4.
Như vậy, ta thấy với 1 code block, ta chỉ cần duyệt qua các dòng trong block đó, với loại 1 thì ta cứ in ra còn loại 2 thì gọi đệ quy để giải quyết cái code block mới.
Về vấn đề xác định xem 1 code block bắt đầu và kết thúc tại đâu, tương ứng với bài toán ghép cặp các dấu ngoặc ‘{’ và ‘}’ trong 1 dãy (Vì 1 code block bắt đầu bởi 1 xâu kết thúc bởi ‘{’ và kết thúc bởi 1 xâu đúng bằng ‘}’ (trừ do {} while (cond);
Tất nhiên là nếu xét cả switch case vào (1 case bắt đầu và kết thúc tại đâu) thì bài toán rắc rối hơn nhưng vẫn giải được và giải được trong O(n).
Các vấn đề còn lại như: tách ‘{’, ‘}’, ‘:’, ‘;’, và tách làm sao phải bỏ qua các trường hợp là những dấu đó lại là 1 ký tự hằng, nối các chuỗi đã tách nếu cần thiết, xử lý dấu tab ‘\t’…chỉ đơn thuần là những vấn đề kỹ thuật nhưng muốn xử lý trọn vẹn thì tương đối khó.
Người thảo luận để tìm ra cách giải hay cho một bài toán khó sẽ trở thành lập trình viên giỏi. Người hay hỏi bài tập thì không. Còn bạn thì sao?