Ikegami của sẽ mất không gian hàm mũ cho để lưu trữ các chuỗi trước khi nó được biến thành regex (mỗi từ sẽ xuất hiện 2 n - 1 lần, trong đó n là số từ, do đó tổng không gian tối thiểu là 2 n - 1 * Tổng (độ dài của từ)). Đây là không liên quan đến công cụ regex - vì vấn đề là trước khi chuỗi được chuyển thành regex.
Một tương đương xây dựng regex (trong nhiệm kỳ của tập hợp các chuỗi rằng nó phù hợp) để giải pháp Ikegami của sẽ là:
^(?=[^ ])(?:(?: |^)John(?= |\z))?+(?:(?: |^)Von(?= |\z))?+(?:(?: |^)Neumann(?= |\z))?+\z
này chỉ chiếm không gian tuyến tính, trong nhiệm kỳ của số từ và tổng chiều dài của tất cả các từ.
Để rõ ràng:
^
(?=[^ ])
(?:(?: |^)John(?= |\z))?+
(?:(?: |^)Von(?= |\z))?+
(?:(?: |^)Neumann(?= |\z))?+
\z
Cái nhìn-phía trước khẳng định (?=[^ ])
có 2 mục đích: ngăn chặn các chuỗi rỗng không bị phù hợp, và chắc chắn rằng các ký tự đầu tiên không phải là một nhân vật không gian.
Lưu ý ?+
, mà làm cho lượng hóa sở hữu (hoặc nguyên tử), vì chúng ta không cần phải quay lại đây. Tại sao? Nếu chúng ta làm điều này bình thường, chúng ta sẽ lặp qua danh sách các từ và so sánh nó với từ bên trái nhất trong đầu vào. Sau khi chúng ta tìm thấy một trận đấu, chúng ta sẽ tiếp tục vòng lặp để so sánh nó với từ tiếp theo trong đầu vào, cho đến khi tất cả các từ trong đầu vào được tìm thấy hoặc chúng ta đã hoàn thành việc lặp lại danh sách các từ.
Số sở hữu số liệu định lượng cũng ngăn chặn xảy ra lỗi địa ngục ngược. Nếu một từ được coi là trùng khớp, từ đó sẽ không bao giờ được xem xét lại.
Đối với mỗi từ, chúng có thể được đặt trước bởi dấu cách hoặc đó là phần đầu của chuỗi. Xác nhận xem trước (?= |\z)
có mục đích đảm bảo các từ có cùng tiền tố không được kết hợp không đúng lúc thử đầu tiên (ví dụ: "John Von Vone"
, thử khớp với "John Vone"
).
Vì không có backtracking, hiệu suất trường hợp xấu nhất là tuyến tính về độ dài của tất cả các từ và độ dài của chuỗi đầu vào (giống như cách bạn sẽ làm điều đó mà không có regex).
Chúng có thể thay regex một chút để cho phép khoảng cách linh hoạt:
^(?= *+[^ ])(?: *+John(?= |\z))?+(?: *+Von(?= |\z))?+(?: *+Neumann(?= |\z))?+ *+\z
Đối với độ rõ nét (không gian hàng đầu có ý nghĩa):
^
(?= *+[^ ])
(?: *+John(?= |\z))?+
(?: *+Von(?= |\z))?+
(?: *+Neumann(?= |\z))?+
*+
\z
Cái nhìn-phía trước (?= *+[^ ])
tại bắt đầu đảm bảo chuỗi đầu vào không chỉ chứa dấu cách.
Regex được thay đổi để cho phép bất kỳ khoảng trắng nào đứng trước một từ (backtracking không được phép bởi định lượng sở hữu). 0 hoặc nhiều định lượng hơn *
được sử dụng, trong trường hợp từ đó là đúng ở đầu chuỗi. Không có cơ hội cho 2 từ va chạm, do xác nhận nhìn phía trước (?= |\z)
.
Nó vẫn chiếm không gian tuyến tính khi xây dựng chuỗi (trước khi nhập nó vào công cụ regex). Hiệu suất trường hợp xấu nhất cũng là tuyến tính.
trường hợp cực
Những lời gốc:
aaaaaaaaaaaaaaaaaaa0 aaaaaaaaaaaaaaaaaaa1 ... aaaaaaaaaaaaaaaaaaa9 aaaaaaaaaaaaaaaaaaaa ... aaaaaaaaaaaaaaaaaaaz aaaaaaaaaaaaaaaaaaaA ... aaaaaaaaaaaaaaaaaaaZ
(Mỗi từ là 20 nhân vật, những thay đổi cuối cùng nhân vật từ 0-9
, sau đó a-z
, sau đó A-Z
)
Strings để tìm kiếm (không phù hợp):
aaaaaaaaaaaaaaaaaaaz aaaaaaaaaaaaaaaaaaay
(y
chỉ có thể đến trước z
)
Từ gốc:
patterns used in Perl pattern matching evolved from those supplied
(Một số từ bình thường)
Các chuỗi để tìm kiếm (không khớp):
patterns used in Perl pattern matching evolved from those suppliedd
(tắm d
vào cuối)
Từ gốc:
aaaaaaaaaaaa aaaaaaaaaaa aaaaaaaaaa aaaaaaaaa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaa
(. Lời chỉ chứa a
, với chiều dài khác nhau)
Strings để tìm kiếm (không phù hợp):
aaaaaaaaaaaa aaaaaaaaaaa aaaaaaaaaa aaaaaaaaa aaaaaaaa aaaaaaa aaaaaa aaaaa aaaaa
(Thêm a
vào cuối)
Từ gốc:
performance abc xyz performance 456 [email protected]# performance
(Same từ xuất hiện nhiều lần)
Strings để tìm kiếm (không phù hợp):
performance performance performance performance
@ogzd được đăng '/^(? =.) (?: \ Bjohn \ b)? \ S * (?: \ Bvon \ b)? \ S * (?: \ Bneumann \ b)? \ Z/i' (với một số trợ giúp). Tôi không chắc tại sao anh ta lại xóa nó. Nó không phải là một giải pháp mục đích chung, nhưng OP có thể không cần một giải pháp mục đích chung. – ikegami
@ikegami: '(? =.)' Cần phải là '(? = \ S)' nếu không mẫu sẽ khớp với một chuỗi các khoảng trắng. – Borodin