Nếu động cơ regexp của bạn cho thấy hành vi mũ thời gian chạy cho (x + x +) + y, sau đó nó là chia vì một DFA hoặc NFA có thể nhận ra mô hình này trong thời gian tuyến tính:
echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | egrep "(x+x+)+y"
echo "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxy" | egrep "(x+x+)+y"
cả câu trả lời ngay lập tức . Trong thực tế, chỉ có một vài trường hợp (như backreferences) trong đó backtracking thực sự cần thiết (chủ yếu là vì regexp với backreference là không phải là một biểu thức chính quy trong ý nghĩa lý thuyết ngôn ngữ nữa). Việc triển khai có khả năng chỉ nên chuyển sang chế độ backtracking khi các trường hợp góc này được đưa ra. Trong sự công bằng, DFA cũng có mặt tối, bởi vì một số regexp có yêu cầu kích thước theo cấp số nhân, nhưng một giới hạn kích thước dễ thực thi hơn ràng buộc thời gian và DFA lớn chạy tuyến tính trên đầu vào, vì vậy nó là một món hời tốt hơn so với một backtracker nhỏ nghẹt thở trên một vài X.
Bạn nên thực sự đọc Russ Cox loạt bài báo xuất sắc về việc thực hiện regexp (và hành vi bệnh hoạn của tùy ý): http://swtch.com/~rsc/regexp/
Để trả lời câu hỏi của bạn về decidability: Bạn không có thể. Vì không có một bản sao cho regexpr. Mỗi thực hiện đều có chiến lược riêng của mình để đối phó với sự tăng trưởng theo hàm mũ trong thuật toán của họ đối với một số trường hợp nhất định và không bao gồm những trường hợp khác. Một quy tắc có thể phù hợp cho ở đây và thảm khốc cho ở đó.
UPDATE:
Ví dụ, một thực thể chứa một ưu mà có thể sử dụng biến đổi đại số để đơn giản hóa regexps trước khi thực hiện chúng: (x+x+)+y
là giống một xxx*y
, mà không phải là một vấn đề đối với bất kỳ backtracker.Nhưng cùng một trình tối ưu hóa sẽ không nhận ra biểu thức tiếp theo và vấn đề là có một lần nữa. Ở đây có người mô tả làm thế nào để phác thảo một regexpr mà đánh lừa ưu Perl:
http://perlgeek.de/blog-en/perl-tips/in-search-of-an-exponetial-regexp.html
Nguồn
2010-07-31 11:04:04
Yeap nhưng bạn nói "có thể là O (2^n)" có cách nào để đảm bảo không? Có cách nào giống như chuyển đổi regexp để nó có thể được hiển thị là không theo cấp số nhân? – mathk