자료구조 공부/String

정규표현식 정리 - 백준 (1013, 2857, 2671, 2870)해설 포함

kdhoooon 2021. 3. 23. 20:55

문자열 문제중 정규표현식 문제와 정규표현식을 따로 정리해 놓겠다.

 

 

정규표현식의 기본 규칙이다.

 

 

자주 사용 되는 규칙이다.

이 외에 규칙들이다.

/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i 이메일
/^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$/ 핸드폰 번호

 

백준 1013 (Contact)


www.acmicpc.net/problem/1013

 

1013번: Contact

입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트 케이스에 대해 전파를 표현하는, { 0, 1 }만으로 이루어진 문자열이 공백 없이 주어진다. 문자열 길이는 (1 ≤

www.acmicpc.net

 

이 문제에서는 문제 자체에 정규식을 어떻게 써야 답을 구할 수 있는지 나와있어서 문제를 푸는 방법 자체는 어렵지 않았다.

 

문제에 적힌 정규식 규칙을 읽어보고 이해하는 것이 더 중요한 문제같다.

 

(100+1+ | 01)+ 를 사용하면 100_1_ (여기서 _ 에는 문자가 1개이상 있으면 된다)01 패턴이 반복되는 코드를 찾을 수 있다.

<전체 코드>

import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;

import javax.management.Query;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class Main {

	static StringBuilder sb = new StringBuilder();
	
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        
        int n = Integer.parseInt(bufferedReader.readLine());
        
        String regex = "(100+1+|01)+";
        
        for(int i = 0 ; i < n ; i++){
        	String test = bufferedReader.readLine();
        	
        	if(Pattern.matches(regex, test)) {
        		sb.append("YES\n");
        	}
        	else {
        		sb.append("NO\n");
        	}
        }
        
        System.out.println(sb);
    }
        
}

 

 

백준 2857번 (FBI)


https://www.acmicpc.net/problem/2857

 

2857번: FBI

5개 줄에 요원의 첩보원명이 주어진다. 첩보원명은 알파벳 대문자, 숫자 0~9, 대시 (-)로만 이루어져 있으며, 최대 10글자이다.

www.acmicpc.net

이 문제의 경우 두가지 풀이법이 존재한다.

정규식 만으로 푸는 문제와

자바에 존재하는 정규식 함수를 이용하여 푸는 방식이다.

 

첩보원명에 FBI가 존재하는지를 확인하면 된다.

정규식 ".*FBI.*" 를 통해 찾을 수 있다.

" .* " -> 이 정규식에서 .  : . 의 위치에 어떤 문자가 와도 된다.

                              *  : 0개이상의 문자가 온다.

이 두가지 규칙이 합쳐져 0개이상의 문자가 .의 위치에 온다. 쉽게말해 모든 단어를 선택할 수 있는 것이다.

 

코딩테스트에서 해당 문자를 포함하는 지를 고르는 문제가 많이 나오니까 알아두면 좋겠다.

<정규식 만으로 찾기>

import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;

import javax.management.Query;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class Main {

	static StringBuilder sb = new StringBuilder();
	
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
               
        String regex = ".*FBI.*";
        int cnt = 0;
        
        for(int i = 1 ; i <= 5 ; i++){
        	String name = bufferedReader.readLine();
        	
        	if(Pattern.matches(regex, name)) {
        		cnt++;
        		sb.append( i + " " );
        	}
        }
        
        if(cnt == 0) {
        	sb.append("HE GOT AWAY!");
        }
        
        System.out.println(sb);
    }
        
}

 

자주 사용되는 정규식 함수

  • matches() -> 패턴에 정확하게 일치하는지 확인
  • replaceAll() -> 패턴에 맞는 값을 새로운 값으로 치환
  • find() -> 패턴에 맞는 값이 하나라도 존재하는지(Boolean)
  • group() -> 패턴에 맞는 값의 첫번째 문자의 위치(Integer)

이렇게 존재한다.

mathces() 함수는

Pattern 에 존재하는 함수다.

 

나머지 함수는 

Matcher 에 존재하는 함수들이다.

 

포함되는지의 유무를 알고 싶은 문제이므로 find() 를 사용하면 된다.

Pattern pattern = Pattern.compile(regex);
Matcher match = pattern.matcher(name); 
        	
if(match.find()) {
	cnt++;
    sb.append( i + " " );
}

Pattern 을 이용해 Matcher 를 생성하는 코드를 익혀놓으면 편하게 사용할 수 있을 것이다.

 

<정규식 함수를 이용한 풀이>

import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;

import javax.management.Query;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class Main {

	static StringBuilder sb = new StringBuilder();
	
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
               
        String regex = "FBI";
        int cnt = 0;
        
        for(int i = 1 ; i <= 5 ; i++){
        	String name = bufferedReader.readLine();
        	
        	Pattern pattern = Pattern.compile(regex);
        	Matcher match = pattern.matcher(name); 
        	
        	if(match.find()) {
        		cnt++;
        		sb.append( i + " " );
        	}
        }
        
        if(cnt == 0) {
        	sb.append("HE GOT AWAY!");
        }
        
        System.out.println(sb);
    }
        
}

 

 

백준 2617(잠수함 식별)


www.acmicpc.net/problem/2671

 

2671번: 잠수함식별

입력에 들어있는 스트링을 읽고, 이것이 잠수함의 엔진소리를 나타내는 스트링인지 아니면 그냥 물속의 잡음인지를 판정한 후, 잠수함의 엔진 소리에 해당하는 스트링이면 "SUBMARINE"을 출력하고

www.acmicpc.net

위의 1013번을 풀어봤으면 쉬운 문제다.

(100~1~|01)~  은 1013번에서 (100+1+|01)+ 와 같은 말이다.

 

<전체 코드>

import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;
import javax.management.Query;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class Main {

	static StringBuilder sb = new StringBuilder();
	
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
               
        String regex = "(100+1+|01)+";
        
        if(Pattern.matches(regex, bufferedReader.readLine())) {
        	sb.append("SUBMARINE");
        }
        else {
        	sb.append("NOISE");
        }
        
        System.out.println(sb);
    }
        
}

 

 

백준 2870 (수학숙제)


www.acmicpc.net/problem/2870

 

2870번: 수학숙제

종이에서 찾은 숫자의 개수를 M이라고 하면, 출력은 M줄로 이루어져야 한다. 각 줄에는 종이에서 찾은 숫자를 하나씩 출력해야 한다. 이때, 비내림차순으로 출력해야 한다. 비내림차순은 내림차

www.acmicpc.net

여기서 사용하는 건

split() 함수다

 

split() 함수는 String 에서 해당 정규표현식에 해당하는 문자가 나오면 나눠주는 역할을 한다.

 

여기서 사용할 정규식은 숫자만 저장을 해야하므로 숫자를 제외한 나머지 문자들이다.

 

"\D"  -  \D 는 숫자를 제외한 나머지 숫자들을 말한다. ( = "[^0-9]")

           여기서 java 는 \ 를 표현하려면 \\ 두개를 적어야 하나가 되므로 밑 코드에선 \\D 가된다. 

 

Integer 을 사용하면 런타임 오류가 뜨므로 

BigInteger 을 이용하여 문제를 풀었다. ( Long 을 사용했는데 런타임 에러가 똑같이 났다)

<전체 코드>

import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;
import javax.management.Query;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class Main {

	static StringBuilder sb = new StringBuilder();
	
    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
               
        int n = Integer.parseInt(bufferedReader.readLine());
        
        List<BigInteger> ans = new LinkedList<BigInteger>();
        
        for(int i = 0 ; i < n ; i++) {
        	String[] line = bufferedReader.readLine().split("\\D");
        	
        	for(int j = 0 ; j < line.length ; j++) {
        		if(!line[j].equals("")) {
        			ans.add(new BigInteger(line[j]));
        		}
        	}
        }
        
        Collections.sort(ans);
       
        for(BigInteger num : ans) {
        	sb.append(num + "\n");
        }
        
        System.out.println(sb);
    }
        
}

 

'자료구조 공부 > String' 카테고리의 다른 글

백준 1701 (Cubeditor)  (0) 2021.04.20
백준 1062 (가르침)  (0) 2021.04.20
백준 1786 (찾기)  (0) 2021.03.23
백준 9935 (문자열 폭발)  (0) 2021.03.19
백준 1958 ( LCS 3)  (0) 2021.03.19