1715번: 카드 정렬하기

정렬된 두 묶음의 숫자 카드가 있다고 하자. 각 묶음의 카드의 수를 A, B라 하면 보통 두 묶음을 합쳐서 하나로 만드는 데에는 A+B 번의 비교를 해야 한다. 이를테면, 20장의 숫자 카드 묶음과 30장

www.acmicpc.net

 

 

 


 

 

  • 생각

 

PriorityQueue를 이용하면 쉽게 풀 수 있는 문제이다.

 

1) 카드 묶음을 PriorityQueue에 담는다.

2) 카드 묶음이 1개 이면 0을 출력한다.

3) 카드 묶음이 2개 이상이면 두 카드를 출력 변수에 더 해주고 queue에도 추가시켜준다.

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;

public class Main {
	static int N;
	static PriorityQueue<Long> queue;
	static long answer;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(answer);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		queue = new PriorityQueue<Long>();
		answer = 0;
		
		for(int i = 0; i < N; i++)
			queue.add(in.nextLong());
		
		TurnQueue();
	}
	
	private static void TurnQueue() {
		while (queue.size() > 1) {
			long firstCard = queue.poll();
			long secondCard = queue.poll();
			
			answer += firstCard + secondCard;
			queue.add(firstCard + secondCard);
		}
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

4179번: 불!

입력의 첫째 줄에는 공백으로 구분된 두 정수 R과 C가 주어진다. 단, 1 ≤ R, C ≤ 1000 이다. R은 미로 행의 개수, C는 열의 개수이다. 다음 입력으로 R줄동안 각각의 미로 행이 주어진다.  각각의 문

www.acmicpc.net

 

 


 

 

 

  • 풀이

 

 

DFS

1. 불을 퍼뜨린다.

2. 지훈이가 이동한다.

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;

public class Main {
	static int N, M;
	static char[][] array;
	static Queue<int[]> jihoon, fire;
	static int[] x = { -1, 0, 1, 0 };
	static int[] y = { 0, 1, 0, -1 };

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println("IMPOSSIBLE");
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		M = in.nextInt();
		array = new char[N][M];
		jihoon = new LinkedList<>();
		fire = new LinkedList<>();

		for (int i = 0; i < N; i++) {
			String s = in.nextLine();
			for (int j = 0; j < M; j++) {
				array[i][j] = s.charAt(j);
				if (array[i][j] == 'F')
					fire.add(new int[] { i, j });
				if (array[i][j] == 'J')
					jihoon.add(new int[] { i, j, 0 });
			}
		}

		bfs();
	}

	private static void bfs() {
		while (!jihoon.isEmpty()) {
			// 불이 먼저 퍼진다.
			int size = fire.size();
			for (int i = 0; i < size; i++) {
				int[] fireLocation = fire.poll();

				for (int direction = 0; direction < 4; direction++) {
					int r = fireLocation[0] + x[direction];
					int c = fireLocation[1] + y[direction];

					if (r < 0 || c < 0 || r >= N || c >= M)
						continue;
					if (array[r][c] == '#' || array[r][c] == 'F')
						continue;

					array[r][c] = 'F';
					fire.add(new int[] { r, c });
				}
			}

			size = jihoon.size();
			for (int i = 0; i < size; i++) {
				int[] jihoonLocation = jihoon.poll();
				for (int direction = 0; direction < 4; direction++) {
					int r = jihoonLocation[0] + x[direction];
					int c = jihoonLocation[1] + y[direction];

					// 나가는 경우
					if (r < 0 || c < 0 || r >= N || c >= M) {
						System.out.println(jihoonLocation[2] + 1);
						System.exit(0);
					}

					if (array[r][c] == '#' || array[r][c] == 'F' || array[r][c] == 'J')
						continue;

					array[r][c] = 'J';
					jihoon.add(new int[] { r, c, jihoonLocation[2] + 1 });
				}
			}
		}
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

14888번: 연산자 끼워넣기

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 

www.acmicpc.net

 

 

 


 

 

 

  • 생각

 

 

dfs ,백트래킹 방식으로 모든 방법을 확인하였다.

 

DFS

1. basecase는 index가 N인 경우로 입력한 숫자를 다 도는 경우를 말한다.

2. 연산자 4개를 하나씩 도는데 여기서 백트래킹 방식으로 작업을 한 뒤 작업이 끝나면 다시 되돌려주는 작업을 한다.

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.InputMismatchException;

public class Main {
	static int N, max, min;
	static int[] array, mathSymbol;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(max + "\n" + min);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		array = new int[N];
		mathSymbol = new int[4];
		max = Integer.MIN_VALUE;
		min = Integer.MAX_VALUE;
		
		for(int i = 0; i < N; i++)
			array[i] = in.nextInt();
		
		for(int i = 0 ; i < 4; i++) {
			mathSymbol[i] = in.nextInt();
		}
		
		dfs(1,  array[0]);
	}
	
	private static void dfs(int index, int value) {
		if(index == N) {
			max = Math.max(max, value);
			min = Math.min(min, value);
		}
		
		for(int j = 0; j < 4; j++) {
			if(mathSymbol[j] == 0)		continue;
				
			mathSymbol[j]--;
			dfs(index + 1, calculate(value, array[index], j));
			mathSymbol[j]++;
		}		
	}
	
	private static int calculate(int a, int b, int symbol) {
		if(symbol == 0)
			return a + b;
		else if(symbol == 1)
			return a - b;
		else if(symbol == 2)
			return a * b;
		else
			return a / b;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

  • 풀이

 

일단 배열을 받으면서 ArrayList에 프로세스의 위치를 추가한다. (단, 가장자리는 전선이 필요없으니 추가 안함)

 

사용 방법은 dfs이다. 사용이유는 모든 경우의 수를 돌아야하고 해당 문제에서 확실하게 돌 수 있는 방법이라 생각했다.

 

DFS

1. basecase는 모든 프로세스를 돌았을 때이다.

2. basecase 안에서는 최대한 많이 연결된 프로세스의 경우 최대 전선 수를 가져온다.

3. basecase에 걸리지 않는 경우는 4방향으로 돌아야한다. (단, 프로세스가 선택되지 않을 경우도 있다.)

4. 4방향 연결이 돌 수 있는지 체크 후 돌린다. (여기선 백트래킹 사용)

 

 

  • 코드
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.InputMismatchException;

public class Solution {
	static int[][] array;
	static ArrayList<int[]> core;
	static int N, answer, maxOfConnectedCore;
	static int[] x = { -1, 0, 1, 0 };
	static int[] y = { 0, 1, 0, -1 };
	static StringBuilder sb;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		int testcase = in.nextInt();
		sb = new StringBuilder();

		for (int i = 1; i <= testcase; i++) {
			N = in.nextInt();
			array = new int[N][N];
			answer = Integer.MAX_VALUE;
			core = new ArrayList<>();

			InputArray(in);

			maxOfConnectedCore = 0;
			dfs(0, 0, 0);
			sb.append("#" + i + " " + answer).append("\n");
		}
	}

	private static void dfs(int depth, int countOfConnectedCore, int countOfLine) {
		// basecase
		if (depth == core.size()) {
			if (maxOfConnectedCore < countOfConnectedCore) {
				maxOfConnectedCore = countOfConnectedCore;
				answer = countOfLine;
			} else if (maxOfConnectedCore == countOfConnectedCore) {
				if (answer > countOfLine)
					answer = countOfLine;
			}

			return;
		}

		for (int i = 0; i < 4; i++) {
			if (CheckConnect(core.get(depth), i)) {
				int count = ConnectLine(core.get(depth), i, 2); // 연결
				dfs(depth + 1, countOfConnectedCore + 1,countOfLine + count);
				ConnectLine(core.get(depth), i, 0); // 연결 해제
			}
		}
		
		dfs(depth + 1, countOfConnectedCore, countOfLine);	// 연결 X
	}

	private static void InputArray(InputReader in) {
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				array[i][j] = in.nextInt();
				if (array[i][j] == 1 && i != 0 && i != N - 1 && j != 0 && j != N - 1)
					core.add(new int[] { i, j });
			}
		}
	}

	private static int ConnectLine(int[] coreIndex, int direction, int value) {
		int count = 0;
		int r = coreIndex[0] + x[direction];
		int c = coreIndex[1] + y[direction];
		while (r >= 0 && c >= 0 && r < N && c < N) {
			array[r][c] = value;
			count++;
			r = r + x[direction];
			c = c + y[direction];
		}
		return count;
	}

	private static boolean CheckConnect(int[] coreIndex, int direction) {
		int r = coreIndex[0] + x[direction];
		int c = coreIndex[1] + y[direction];
		while (r >= 0 && c >= 0 && r < N && c < N) {
			if (array[r][c] != 0)
				return false;
			r = r + x[direction];
			c = c + y[direction];
		}
		return true;
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

16570번: 앞뒤가 맞는 수열

수열 (a1, a2, ⋯, aN) 이 다음의 성질을 가지면 그 수열은 k-앞뒤수열 이라고 한다. (a1, a2, ⋯, ak) = (aN-k+1, aN-k+2, ⋯ , aN), 1 ≤ k < N 어떤 수열이 k-앞뒤수열일 때, k의 최댓값 k*를 그 수열의 앞뒤계

www.acmicpc.net

 

 

 

 


 

 

 

  • 생각

 

 

KMP알고리즘으로 풀면 쉽게 풀 수 있을 것 같다.

 

 

 

 

  • 코드

 

import java.io.IOException;
import java.io.InputStream;
import java.util.InputMismatchException;

public class Algorithm {
	static int[] array, pi;
	static int N;

	public static void main(String[] args) throws Exception {
		SetData();
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		array = new int[N];
		pi = new int[N];

		for (int i = N - 1; i >= 0; i--) {
			array[i] = in.nextInt();
		}

		KMP();

		int length = 0, count = 0;
		for (int i = 0; i < N; i++) {
			if (pi[i] > length) {
				length = pi[i];
				count = 0;
			}
			if (pi[i] == length)
				count++;
		}
		if (length == 0)
			System.out.println("-1");
		else
			System.out.println(length + " " + count);
	}

	public static void KMP() {
		int j = 0;
		for (int i = 1; i < N; i++) {
			while (j > 0 && array[j] != array[i]) {
				j = pi[j - 1];
			}
			if (array[j] == array[i]) {
				pi[i] = ++j;
			}
		}
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

 

  • KMP 알고리즘이 아니여도 풀 수 있는 문제이다.

 

import java.io.IOException;
import java.io.InputStream;
import java.util.InputMismatchException;

public class Algorithm {
	static int[] array, pi;
	static int N;

	public static void main(String[] args) throws Exception {
		SetData();
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		array = new int[N + 1];
		pi = new int[N + 1];

		for (int i = 1; i <= N; i++) {
			array[i] = in.nextInt();
		}

		KMP();

		for (int i = N; i >= 1; i--) {
			if (pi[i] != 0) {
				System.out.println(i + " " + pi[i]);
				System.exit(0);
			}
		}

		System.out.println(-1);
		
	}

	static void KMP() {
		for (int i = N - 1; i >= 1; i--) {
			int count = 0;
			int j = N;
			int index = i;
			while (array[index--] == array[j--]) {
				count++;
			}
			pi[count]++;
		}
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

1786번: 찾기

첫째 줄에, T 중간에 P가 몇 번 나타나는지를 나타내는 음이 아닌 정수를 출력한다. 둘째 줄에는 P가 나타나는 위치를 차례대로 공백으로 구분해 출력한다. 예컨대, T의 i~i+m-1번 문자와 P의 1~m

www.acmicpc.net

 

 

 


 

 

 

  • 생각

 

O(nm)으로 풀면 쉽게 풀 수 있는 문제이지만, 시간제한으로 O(n) 시간복잡도로 풀어야하는 문제이다. 

이런 문자열(ctrl + f로 찾는 기능)을 푸는 문제에서 활용할 수 있는 알고리즘이 있다.

KMP 알고리즘으로 풀면 O(n + m)의 시간복잡도로 풀 수 있다.

 

 

  • 코드

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.List;

public class Main {
	static StringBuilder sb;
	static int start, count;
	static List<Integer> list;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(list.size() + "\n" + sb);
	}

	// 데이터
	private static void SetData() throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		String t = br.readLine();
		String p = br.readLine();
		sb = new StringBuilder();
		list = new ArrayList<Integer>();
		count = 0;

		KMP(t, p);
		for(int value : list) {
			sb.append(value).append(" ");
		}
	}
	
	// KMP 알고리즘 - pi[] 배열에서 주어진 문자열의 인덱스 0부터 i까지의 부분 문자열 중
	// 접두사 == 접미사가 되는 가장 긴 접두사의 길이를 넣는다.
	// 현재 밑 코드에서 접두사는 j(왼쪽), 접미사는 i(오른쪽)이다.
	static void KMP(String s, String pattern) {
		int[] pi = getPi(pattern);
		int j = 0;
		int strLen = s.length();
		int patternLen = pattern.length();
		
		for(int i = 0; i < strLen; i++) {
			while(j > 0 && s.charAt(i) != pattern.charAt(j)) { // 다르면 같았던 다음 접미사로 바로 건너뛰기 
				j = pi[j - 1];
			}
			
			if(s.charAt(i) == pattern.charAt(j)) {
				if(j + 1 == patternLen) { // pattern 문자열 전부가 같다면
					list.add(i - j + 1); // 전체 문자열 중 패턴 문자열과 같은 문자열의 시작 인덱스를 구해야 하므로(게다가 1부터 시작함)
					j = pi[j]; // 초기화
				}
				else { // 바로 다음번째 문자를 가지고 비교해야 하므로 
					j++;
				}
			}
		}
	}

	static int[] getPi(String p) {
		int[] pi = new int[p.length()];
		int j = 0;
		for (int i = 1; i < p.length(); i++) {
			while (j > 0 && p.charAt(i) != p.charAt(j)) { // j > 0 인 이유는 최소 두 글자부터 비교하기 위함
				j = pi[j - 1]; // 다르면 이전의 문자열에서 접두사 - 접미사 같은 최대 길로 이동시킨다.
			}
			if (p.charAt(i) == p.charAt(j))
				pi[i] = ++j;
		}

		return pi;
	}

}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

5052번: 전화번호 목록

첫째 줄에 테스트 케이스의 개수 t가 주어진다. (1 ≤ t ≤ 50) 각 테스트 케이스의 첫째 줄에는 전화번호의 수 n이 주어진다. (1 ≤ n ≤ 10000) 다음 n개의 줄에는 목록에 포함되어 있는 전화번호가

www.acmicpc.net

 

 

 

 


 

 

 

 

  • 생각

 

입력한 모든 숫자 중 한 가지의 숫자가 다른 숫자에 시작으로 포함되어있으면 안되는 문제이다.

 

이때 정수로 오름차순 정렬하면 정말 크고작은 수대로 정렬이 되기때문에 원하는 대로 정렬이 안된다.

여기서 문자열로 받은다음 정렬하면 원하는대로 정렬 될것이다.

그래서 정렬 후 i-1인덱스의 값이 i인덱스의 값에 startsWith를 사용해서 접두어 관계를 가지는지 확인만 해주면 된다.

 

 

 

 

  • 코드

 

 

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.InputMismatchException;

public class Main {
	static StringBuilder sb;
	static int N, L, answer;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(sb);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		int testcase = in.nextInt();
		sb = new StringBuilder();
		int n;
		boolean check;
		
		for(int i=0;i<testcase;i++)
		{
			check = false;
			n = in.nextInt();
			String[] array = new String[n];
            for(int j=0;j<n;j++) {
                array[j]=in.nextLine();
            }
            
            //정렬과 스위치 구현
            Arrays.sort(array, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o1.compareTo(o2);                    
                }
            });
            
            for(int j=1;j<n;j++) {
                if(array[j].startsWith(array[j-1])) {
                    check=true;
                    break;
                }
            }
            
            if(check) sb.append("NO").append("\n");
            else sb.append("YES").append("\n");
		}		
	}
	
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

 

  • 트라이 방법?

트라이 방법으로 풀 수 있다고하는데 속도는 빠르지만 메모리를 너무 많이 잡아먹어서 장단점이 있는 것 같다.

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int TC = Integer.parseInt(br.readLine());

        root:
        for (int tc = 0; tc < TC; tc++) {
            int n = Integer.parseInt(br.readLine());
            HTrie root = new HTrie('r', true);
            boolean check = true;
            for (int i = 0; i < n; i++) {
                char[] input = br.readLine().toCharArray();
                if (check) {
                    if (!root.insert(input)) {
                        check = false;
                    }
                }
            }
            if (check) {
                System.out.println("YES");
            } else {
                System.out.println("NO");
            }
        }
    }


    static class HTrie {
        char number;
        boolean isRoot;
        boolean isEnd;
        HTrie[] children;

        HTrie(char number, boolean isRoot) {
            this.number = number;
            this.isRoot = isRoot;
            children = new HTrie[10];
        }

        boolean insert(char[] numbers) {
            HTrie t = this;

            for (int i = 0; i < numbers.length; i++) {
                char c = numbers[i];
                int id = c - '0';

                if (t.children[id] == null) {
                    t.children[id] = new HTrie(c, false);
                } else {
                    if (t.children[id].isEnd && i != numbers.length - 1) {
                        return false;
                    }

                    if (i == numbers.length - 1) {
                        return false;
                    }
                }

                t = t.children[id];

                if (i == numbers.length - 1) {
                    t.isEnd = true;
                }
            }

            return true;
        }
    }
}

 

14890번: 경사로

첫째 줄에 N (2 ≤ N ≤ 100)과 L (1 ≤ L ≤ N)이 주어진다. 둘째 줄부터 N개의 줄에 지도가 주어진다. 각 칸의 높이는 10보다 작거나 같은 자연수이다.

www.acmicpc.net

 

 

 

 


 

 

 

  • 생각

 

바로 구현하면 되는 문제이다.

 

해당 기준으로 모든 행과 열을 확인했다.

1. 모든 행과 열은 왼쪽부터 오른쪽, 오른쪽부터 왼쪽 다 확인한다. (이전 블럭보다 작은 경우만 확인하기 때문)

2. 이전 블럭보다 -2가 작으면 해당 행이나 열은 되지 않는다.

3. 이전 블럭보다 -1이면 count를 세면서 되돌아올때 해당 블럭은 체크안하기 위해서 체크를 한다. (boolean배열 사용)

4. 이미 count가 1이상인데 이전 블럭보다 높거나 같은 블럭이 나오면 안된다.

5. count가 L만큼 되면 이전 블럭(현재 블럭으로)과 count를 초기화한다.

6. 이전 블럭보다 큰 블럭이 나오면 이전블럭을 현재 블럭으로 변경해준다.

 

 

 

 

  • 코드

 

 

import java.io.IOException;
import java.io.InputStream;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.Queue;

public class Algorithm {
	static int[] x =  { -1, 0, 1, 0 };
    static int[] y = { 0, 1, 0, -1 };
	static int[][] array;
	static int N, L, answer;

	public static void main(String[] args) throws Exception {
		SetData();
		System.out.println(answer);
	}

	// 데이터
	private static void SetData() throws Exception {
		InputReader in = new InputReader(System.in);

		N = in.nextInt();
		L = in.nextInt();
		array = new int[N][N];
		answer = 0;
		
		for(int i = 0; i < N; i++) {
			for(int j = 0; j < N; j++) {
				array[i][j] = in.nextInt();
			}
		}
		
		Calculate();
	}
	
	private static void Calculate() {
		// 가로
		for(int i = 0; i < N; i++) {
			// ->
			boolean check = false;		// 중간에 안되면 반복문을 중단시킬 수단
			boolean[] visit = new boolean[N];	// 겹치는 경우를 방지
			int pre = array[i][0];		// 이전 값
			int count = 0;
			for(int j = 1; j < N; j++) {
				// 이전 값보다 -2가 작으면 바로 종료
				if(pre - 1 > array[i][j]) 	{
					check = true;
					break;
				}
				
				// 이전 값 -1이면 count시작
				if(pre - 1 == array[i][j]) {
					visit[j] = true;		// 겹치는 경우 방지 (>> 갔다가 << 작업해주는데 이 경우 방지)
					count++;
				}
				
				// 이미 -1칸이 1개 나왔는데 pre값보다 큰값이 나오면 반복문 빠져나옴( L개수가 나오지 않았음)
				if(count >= 1 && pre <= array[i][j]) {
					check = true;
					break;
				}
				
				// L개수만큼 나오면 count와 pre값 초기화
				if(count >= L) {
					count = 0;
					pre = array[i][j];
				}
				
				// pre보다 큰값이 나오면 초기화
				if(pre < array[i][j]) pre = array[i][j];
			}
			if(check || (count != 0 && count < L))
				continue;
			
			// <-
			pre = array[i][N-1];
			count = 0;
			for(int j = N -2; j >= 0; j--) {
				if(pre - 1 > array[i][j]) 	{
					check = true;
					break;
				}
				
				if(pre - 1 == array[i][j]) {
					count++;
					if(visit[j]) {
						check = true;
						break;
					}
						
				}
				
				if(count >= 1 && pre <= array[i][j]) {
					check = true;
					break;
				}
				
				if(count >= L) {
					count = 0;
					pre = array[i][j];
				}
				if(pre < array[i][j]) pre = array[i][j];
			}
			if(check || (count != 0 && count < L))
				continue;
			
			answer++;
		}
		
		// 세로
		for(int i = 0; i < N; i++) {
			// 위
			boolean check = false;
			boolean[] visit = new boolean[N];
			int pre = array[0][i];
			int count = 0;
			for(int j = 1; j < N; j++) {
				if(pre - 1 > array[j][i]) 	{
					check = true;
					break;
				}
				
				if(pre - 1 == array[j][i]) {
					count++;
					visit[j] = true;
				}
				
				if(count >= 1 && pre <= array[j][i]) {
					check = true;
					break;
				}
				
				if(count >= L) {
					count = 0;
					pre = array[j][i];
				}
				if(pre < array[j][i]) pre = array[j][i];
			}
			if(check || (count != 0 && count < L))
				continue;
			
			// 밑
			pre = array[N-1][i];
			count = 0;
			for(int j = N -2; j >= 0; j--) {
				if(pre - 1 > array[j][i]) 	{
					check = true;
					break;
				}
				
				if(pre - 1 == array[j][i]) {
					count++;
					if(visit[j]) {
						check = true;
						break;
					}
						
				}
				
				if(count >= 1 && pre <= array[j][i]) {
					check = true;
					break;
				}
				
				if(count >= L) {
					count = 0;
					pre = array[j][i];
				}
				if(pre < array[j][i]) pre = array[j][i];
			}
			if(check || (count != 0 && count < L))
				continue;
			
			answer++;
		}
	}
}

class InputReader {
	private final InputStream stream;
	private final byte[] buf = new byte[8192];
	private int curChar, snumChars;

	public InputReader(InputStream st) {
		this.stream = st;
	}

	public int read() {
		if (snumChars == -1)
			throw new InputMismatchException();
		if (curChar >= snumChars) {
			curChar = 0;
			try {
				snumChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (snumChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int nextInt() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public long nextLong() {
		int c = read();
		while (isSpaceChar(c)) {
			c = read();
		}
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		long res = 0;
		do {
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public int[] nextIntArray(int n) {
		int a[] = new int[n];
		for (int i = 0; i < n; i++) {
			a[i] = nextInt();
		}
		return a;
	}

	public String nextLine() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}

	public boolean isSpaceChar(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	private boolean isEndOfLine(int c) {
		return c == '\n' || c == '\r' || c == -1;
	}
}

 

 

+ Recent posts