[백준] 문자열 문제 정리

백설기·2022년 2월 15일
0

백준 문풀

목록 보기
3/7

2022.02.10 네이버 블로그에 작성했던 것!

10809번 알파벳 찾기

|contains|문자열에 검색하고자 하는 문자가 있는지 확인 / 포함:true 미포함:false|

|indexOf|문자열에서 검색하는 문자의 위치를 반환 / 포함:문자 위치 미포함:-1|

|matches|정규식을 이용하여 문자열을 검색한다./ 특정 문자열을 검색할 때 사용하기보다는 한글, 숫자와 같이 해당 형태의 텍스트가 존재하는지 확인할 때 사용하면 좋다./ 포함:true 미포함:false|

package 백준문자열;
import java.util.*;
public class 알파벳찾기 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc= new Scanner(System.in);
		String str=sc.next();
			for(char c='a';c<='z';c++) {
					System.out.print(str.indexOf(c)+" ");
				}
		}	
	}

구글링해서 찾아낸 다른 분 코드

import java.util.Scanner;
 
public class Main {
 
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
 
 
		int[] arr = new int[26];
		
		for(int i = 0; i < arr.length; i++) {
			arr[i] = -1;
		}
 
		String S = in.nextLine();
 
		for(int i = 0; i < S.length(); i++) {
			char ch = S.charAt(i);
    
			if(arr[ch - 'a'] == -1) {	// arr 원소 값이 -1 인 경우에만 초기화
				arr[ch - 'a'] = i;
			}
		}
 
		for(int val : arr) {	// 배열 출력
			System.out.print(val + " ");
		}
	}
}
  • 먼저 배열을 만들고, 배열 기본값으로 -1을 설정

그다음 Scanner 받아서 S 문자열을 문자 ch로 받고

arr[ch-'a']=i로 ch의 문자 위치를 arr 배열 값으로 바꿈

if문에서 arr[ch-'a']==-1라는 조건을 추가해서 ch에 해당하는 문자가 있을 떄만 i로 바꾸게 함

동일한 문자가 나올 땐 걱정 ㄴㄴ 이미 앞선 동일 문자 값을 i로 바꿨기 때문에..

2675번 문자열 반복

package 백준문자열;
import java.util.*;
public class 문자열반복 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		for(int i=0;i<n;i++) {
			int R=sc.nextInt();
			String S=sc.next();
			for(int j=0;j<S.length();j++) {
				for(int k=0;k<R;k++)
				    {System.out.print(S.charAt(j));}
		}
            System.out.println();
		}
	}
}
  • 놓친 부분:

    	1.배열 굳이 안사용해도 괜찮은데 사용하려해서 헷갈림
    
    	2. 문자열에도 length() 사용 가능하군
    
    	3. for문 속 for문 속 for문도 가능했군 ,,,,,,,, 젤 안 속 for문을 간과함
    
    	4.무엇보다 입력 부분에서 2 3 ABC 5 /HTP0라고 연달아 입력해야하는 줄 알고 안쪽 for문을 안쓸뻔

1152번 단어의 개수

import java.util.*;
public class 단어의개수 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		String str=sc.nextLine(); 
		String[] arr=str.trim().split(" "); //trim은 앞 뒤 공백만 없애줌
		System.out.println(arr.length);
		
	}
}

위에는 나의 틀린 풀이,,

import java.util.*;
public class 단어의개수 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		String str=sc.nextLine(); 
		String[] arr=str.trim().split(" "); //trim은 앞 뒤 공백만 없애줌
		if(arr[0].length() == 0) {
			System.out.println(0);
			return;
		}
		System.out.println(arr.length);
	}
}

맞은 풀이

공백만 존재하는 단어가 있을 때 틀릴 수 있으니 if문 조건 넣고

arr[0].length() == 0와 같이 공백 여부 확인함

5622번 다이얼

package 백준문자열;
import java.util.*;
public class 다이얼 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String num=sc.next();
		int cnt=0;
		for(int i=0;i<num.length();i++) {
			switch(num.charAt(i)) {
			case 'A':
            case 'B':	
            case 'C':cnt+=3;   
                break;
            case 'D':
            case 'E':	
            case 'F':cnt+=4;
                break;
            case 'G':
            case 'H':	
            case 'I':cnt+=5;
				break;
            case 'J':
            case 'K':
            case 'L':cnt+=6;
				break;
            case 'M':
            case 'N':
            case 'O':cnt+=7;
                break;
            case 'P':
            case 'Q':
            case 'R':
            case 'S':cnt+=8;
				break;
            case 'T':
            case 'U':
            case 'V':cnt+=9;
				break;
            case 'W':
            case 'X':
            case 'Y':
            case 'Z':cnt+=10;
				break;
		
			}
			
	
		}
		System.out.println(cnt);
	}
}

내 코드

switch case 문에서 자바에서는 case 'A', 'B', 'C': 이런 식으로 해도 돼서 백준에 입력했더니 컴파일 에러 계속 뜸.. 중복되었다고..

그래서 저리 바꿈

 import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.next();

		// 문자열을 char형 배열로 반환
        char[] chars = str.toCharArray();
		
        // 총 걸리는 시간을 저장할 int형 변수
        int sum = 0;
        // foreach 반복문, char[] 배열 안에 값들을 하나씩 char형으로 처리
        for (char c : chars) {
		// 알파벳이 ABC 중 하나라면 + 3초
            if (c >= 'A' && c <= 'C') {
                sum += 3;
		// 알파벳이 DEF 중 하나라면 + 4초
            } else if (c >= 'D' && c <= 'F'){
                sum +=4;
		// 알파벳이 GHI 중 하나라면 + 5초
            } else if (c >= 'G' && c <= 'I'){
                sum +=5;
		// 알파벳이 JKL 중 하나라면 + 6초
			}else if (c >= 'J' && c <= 'L'){
                sum +=6;
		// 알파벳이 MNO 중 하나라면 + 7초
            }else if (c >= 'M' && c <= 'O'){
                sum +=7;
		// 알파벳이 PQRS 중 하나라면 + 8초
            }else if (c >= 'P' && c <= 'S'){
                sum +=8;
		// 알파벳이 TUV 중 하나라면 + 9초
            }else if (c >= 'T' && c <= 'V'){
                sum +=9;
		// 알파벳이 WXYZ 중 하나라면 + 10초
            }else if (c >= 'W' && c <= 'Z'){
                sum +=10;
            }
        }
        System.out.println(sum);
    }
}

if문 사용한 다른 분 답

1316번 그룹단어체커

package 백준배열;
import java.util.Scanner;
public class 그룹단어체커 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int n=sc.nextInt();
		int num=0, cnt=0;
		String[] arr=new String[3];
		for(int i=0;i<n;i++) {
			arr[i]=sc.next();
			char ch=arr[i].charAt(0);
			for(int j=i+1;j<n;j++) {
				if(arr[i-1]!=arr[i]) {
					cnt=1;
					if(arr[i]==arr[j]) {
						cnt=0;
					}
				}
				else {
					cnt=1;
					if(arr[i-1]!=arr[i]) {
						if(arr[i]==arr[j]) {
						cnt=0;
						}
					}		
				}
			}
			num+=cnt;
			System.out.println(num);
		}
	}
}

내가 짠 코드

if문으로 고려해서 하면 될 거 같았는데 생각보다 케이스가 많다

구글링해서 본 코드는 boolean 함수를 이용해서 그룹단어인지 아닌지 여부만 판단!

import java.util.Scanner;
 
public class Main {
 
	static Scanner in = new Scanner(System.in);
 
	public static void main(String[] args) {
 
		int count = 0;
		int N = in.nextInt();
 
		for (int i = 0; i < N; i++) {
			if (check() == true) {
				count++;
			}
		}
		System.out.println(count);
	}
 
	public static boolean check() {
		boolean[] check = new boolean[26];
		int prev = 0;
		String str = in.next();
		
		for(int i = 0; i < str.length(); i++) {
			int now = str.charAt(i);	// i 번째 문자 저장 (현재 문자)
			
			
			// 앞선 문자와 i 번째 문자가 같지 않다면?
			if (prev != now) {		
				
				// 해당 문자가 처음 나오는 경우 (false 인 경우)
				if ( check[now - 'a'] == false ) {
					check[now - 'a'] = true;		// true 로 바꿔준다
					prev = now;					// 다음 턴을 위해 prev 도 바꿔준다 
				}
	 
				// 해당 문자가 이미 나온 적이 있는 경우 (그룹단어가 아니게 됨) 
				else {
					return false;	//함수 종료
				}
			}
	        
	        
			// 앞선 문자와 i 번째 문자가 같다면? (연속된 문자)
			// else 문은 없어도 됨
			else {
				continue;
			}
		}    
		return true;
	}
}

알고리즘에서 가장 중요하게 작용할 변수 prev 를 생성한다.

prev 의 역할은 이후 반복문에서 문자를 꺼내올 때 앞선 문자와 연속되는지, 아닌지를 판별하기 위함이다.

즉, 아래와 같이 돌아가도록 할 것이다.

prev 의 문자와 해당 문자가 같다면?

→ 해당 문자가 중복된 문자인지 여부를 검사하지 않는다. (boolean 배열)

prev 의 문자와 해당 문자가 다르다면?

→ 해당 문자가 중복된 문자인지 여부를 검사한다. (boolean 배열)

주의할 점!

메인 함수와 check 함수에서도 Scanner 을 쓰므로 반드시 main 함수 밖에 전역 변수로 static 을 붙여 Scanner 을 생성해주어야 한다.

또한 문자열을 입력받을 때 nextLine() 을 쓰면 에러 난다. (개행이 버퍼에 남아있어서 다음 입력때 개행이 str 에 저장된다.)

놓친 부분:

1. boolean 함수로 그룹단어 체크 여부를 참/거짓으로 판단할 줄이야..

2. 단어만 받을 수 있다는 생각이 들어 char ch 이렇게 변수를 설정했는데, int 와 같이 아스키코드를 이용하여 숫자로 간편하게 비교할 수 있다니..!

3. boolean 배열에 원소 있고 없고 여부를 true/false로 생각하면 함수 이용해서 구하기 쉽다

4. 함수 속 '다음 부분 설정 위해 prev=now로 설정하는 거 놓치면 x

5.check[now-'a'] 배열은 중복 여부를 확인해줄 수 있는 boolean 배열이다.
ex) aba 단어 넣으면 세번째 a에서 true 값이 이미 나온 상태

1157번 단어 공부

package 백준배열;
import java.util.Scanner;
public class 단어공부 {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		String str=sc.next();
		String strup=str.toUpperCase();
		int[] count=new int[26];
		char most='a';
		int num=0;
		String Alphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		for(int i=0;i<str.length();i++) {
			for(int j=0;j<Alphabet.length();j++) {
				if(strup.charAt(i)==Alphabet.charAt(j)) {
					count[j]+=1;
				}
				if(count[j]>num) {
					most=Alphabet.charAt(j);
					num=count[j];
						}
			}
		for(int m=0;m<Alphabet.length();m++) {
			for(int n=m+1;n<Alphabet.length();n++) {
				if(count[m]!=0) {
					if(count[m]==count[n]&&count[m]==num) {
						most='?';
					}
			}
		}
			}
		}

		System.out.println(most);
	}
}

노가다 끝에 맞췄다!

import java.util.Scanner;
 
public class Main {
 
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
 
		int[] arr = new int[26]; // 영문자의 개수는 26개임
		String s = in.next();
 
		for (int i = 0; i < s.length(); i++){
 
			if ('A' <= s.charAt(i) && s.charAt(i) <= 'Z') { // 대문자 범위
				arr[s.charAt(i) - 'A']++;	// 해당 인덱스의 값 1 증가
			}
    
			else {	// 소문자 범위
				arr[s.charAt(i) - 'a']++;
			}
		}
 
 
		int max = -1;
		char ch = '?';
 
		for (int i = 0; i < 26; i++) {
			if (arr[i] > max) {
				max = arr[i];
				ch = (char) (i + 65); // 대문자로 출력해야하므로 65를 더해준다.
			}
			else if (arr[i] == max) {
				ch = '?';
			}
		}
 
		System.out.print(ch);
	}
 
}

2941번 크로아티아 알파벳

package 백준배열;
import java.util.Scanner;
public class 크로아티아알파벳 {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		String[] arr= {"c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z=","e", "a", "k"};
		String str=sc.next();
		int cnt=0;
		for(int i=0;i<arr.length;i++) {
			if(str.contains(arr[i])) {
				cnt+=1;}
			
			if(str.contains("dz=")) {
					cnt-=1;
				
			}
		}
		System.out.println(cnt);
	}
}

나의 코드

  • 아래는 구글링해서 얻은 고수분의 해설!

    	이 알고리즘대로 작성해서 만들면 자바의 경우 다음과 같은 에러를 발견할 수 있을 것이다.
    
    	java.lang.StringIndexOutOfBoundsException
    
    	즉 인덱스 참조 범위를 벗어났다는 것이다. ( = 참조할 수 없는 범위 )
    
    	왜일까?
    
    	예로들어 이러한 문자를 받았다고 생각해보자.
    
    	aedzdz=ls=c
    
    	그림으로 보자면 다음과 같을 것이다.
    
    	한번 위의 알고리즘대로 하나씩 해보면 알 수 있을 것이다.
    
    	i 가 10 일 때 반복문을 생각해보자.
    
    	그럼 str.charAt(10) 을 통해 ch 에 저장되고 ( ch = 'c' )
    
    	c 라는 문자를 받았기 때문에 첫 번째 조건문을 실행시키게 된다.

    그리고 여기서 문제가 발생한다.

    if( str.charAt(i + 1) == '=' )

    	aedzdz=ls=c 이 문자열에서 마지막 c 다음의 문자는 존재 하지 않는다.
    	그런데 charAt() 을 통해 참조하려고 하니까 StringIndexOutOfBoundsException 이라는 에러를 뱉는 것이다.
    
    	해결방법은 무엇일까?
    
    	간단하다. 현재 i 의 값이 문자열 길이(str.length) 에서 -1 값보다 작을 경우에만 다음 조건문을 실행시키면 된다.
    
    	( dz= 를 검사할 때는 i 가 str.length - 2 보다 작아야한다. )
import java.util.Scanner;
 
public class Main {
	public static void main(String[] args) {
    
		Scanner in = new Scanner(System.in);
        
		String str = in.nextLine();
        
		int count = 0;
 
		for (int i = 0; i < str.length(); i++) {
 
			char ch = str.charAt(i);
 
			if(ch == 'c') {			// 만약 ch 가 c 라면?
				if(i < str.length() - 1) {
					if(str.charAt(i + 1) == '=') {		//만약 ch 다음 문자가 '=' 이라면?
						// i+1 까지가 하나의 문자이므로 다음 문자를 건너 뛰기 위해 1 증가
						i++;		
					}
					else if(str.charAt(i + 1) == '-') {
						i++;
					}
				}
			}
		    
			else if(ch == 'd') {
				if(i < str.length() - 1) {
					if(str.charAt(i + 1) == 'z') {
						if(i < str.length() - 2) {
							if(str.charAt(i + 2) == '=') {	// dz= 일 경우
								i += 2;
							}
						}
					}
		        
					else if(str.charAt(i + 1) == '-') {	// d- 일 경우
						i++;
					}
				}
			}
		    
			else if(ch == 'l') {
				if(i < str.length() - 1) {
					if(str.charAt(i + 1) == 'j') {	// lj 일 경우
						i++;
					}
				}
			}
		    
			else if(ch == 'n') {
				if(i < str.length() - 1) {
					if(str.charAt(i + 1) == 'j') {	// nj 일 경우
						i++;
					}
				}
			}
 
			else if(ch == 's') {
				if(i < str.length() - 1) {
					if(str.charAt(i + 1) == '=') {	// s= 일 경우
						i++;
					}
				}
		    }
 
			else if(ch == 'z') {
				if(i < str.length() - 1) {
					if(str.charAt(i + 1) == '=') {	// z= 일 경우
						i++;
					}
				}
			}
		    
			count++;
 
		}
 
		System.out.println(count);
	}
}

놓친 부분: 이 알고리즘도 머리 속에 생각을 했었는데, 이걸 다 언제 일일이 입력하지 귀찮아서 넘겼다.. 해볼걸

그리고 위에 복붙한 사진처럼 c 다음 들어올 단어가 없기에 if(i<str.length()-1)이 조건을 넣은 걸 체크 잘 해야할듯!

profile
뭐든지 할 수 있따 🐶

0개의 댓글