Hỏi phương pháp viết một regular expression (regex) mô tả nhiều pattern

Bữa trước tui có làm một bài về chuỗi trên mạng có đề như sau:

A system of Online Q&A needs user’s questions to be standardized.

A standardized question must satisfy this following rules:

  • Common rules: Question only contains letter ( a-zA-Z ), number( 0-9 ), comma( , ), space( ' ' ), question mark ( ? ) characters. Other character should be replaced by space.
  • Space ( ' ' ) rules:
    No space in the head of the sentence, no space at the end of the sentence. No more than 1 space between the words in 1 sentence.
    There must be a letter or number after a space.
  • Comma ( , ) rules:
    There must be a letter or number before a comma and only 1 space after a comma.
  • Uppercase / lowercase rules:
    The first letter in a sentence must be an uppercase
    All of the other letters in a sentence must be lowercase except for the first letter.
  • Question mark ( ? ) rules:
    There is always has one question mark at the end of the sentence.
    There must be 1 letter or number before a question mark.
    If the question mark appears in the middle of the sentence then replace the question mark by a space.

Example:

  • For s="this is not a relevant question , is it???" , the output should be questionCorrection(s) = "This is not a relevant question, is it?"
  • For s="who are you,,???" , the output should be questionCorrection(s) = "Who are you?"

Input/Output:

  • [execution time limit] 0.5 seconds
  • [input] string s
    string of input letters which contains atleast one letter ( a-zA-Z )
  • [output] string
    String of letters which are standardized according to the rules of system

Đây code của tui:

public static String questionCorrection(String s) {
    s = s.toLowerCase();
    s = s.replaceAll("[^a-z0-9\\s,]", " ");
    s = s.replaceAll("[^a-z0-9]+,", ",");
    s = s.replaceAll("[,]", ", ");
    s = s.replaceAll("[\\s]+", " ");
    s = s.replaceAll("^[\\s,]+", "");
    s = s.replaceAll("[\\s,]+$", "");
    String temp = "" + (char)(s.charAt(0) - 32);
    for(int i = 1; i < s.length() ; i++){
        temp += s.charAt(i);
    }
    s = temp + "?";
    return s;

Dù đúng với yêu cầu đề bài nhưng tốc độ chạy khá chậm (10 case test), tổng thời gian từ 0.1s tới 0.2s . Tui run code đáp án mẫu (javascript) thì chỉ mất có 0.02s. Trong đó tui thấy nó dùng kỹ thuật viết một regex để mô tả nhiều pattern, tui thực sự không hiểu lắm mong ai đó giúp đỡ ạ.
Xin cảm ơn.
Code mẫu:

function questionCorrection(s){
    s = s.toLowerCase();
    s = s.replace(/[^A-Za-z0-9,]/g, ' ');
    s = s.replace(/^[^A-Za-z0-9]+/, '');
    s = s.replace(/[^A-Za-z0-9]+$/, '');
    s = s.replace(/(?<=[A-Za-z0-9])([^A-Za-z0-9]+)(?=[A-Za-z0-9])/g, m => { // không hiểu dòng này
        if (/^[\s]+$/.test(m)) return ' ';
        return ', ';
    });
    s = s[0].toUpperCase() + s.slice(1) + '?';
    return s;
}

Bạn phải sử dụng trực tiếp đối tượng Matcher.

5 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?