숫자로 구성된 문자열이 주어진다. 문자 사이에 공백을 적절히 추가해서 개 이상의 부분문자열로 나누려고 한다.
단, 아래 조건을 만족해야 한다.
- 각 부분문자열이 나타내는 수는 오름차순이어야 한다. 단, 한 번의 예외를 둘 수 있다.
- 가능한 많은 부분문자열을 만들어야 한다.
각 부분문자열이 나타내는 수가 오름차순이라는 것은 모든 인접한 두 수에 대해 오른쪽의 수가 왼쪽의 수보다 크거나 같음을 의미한다. 여기에서 한 번의 예외를 둘 수 있다는 것은 최대 하나의 경우에 대해 왼쪽의 수가 오른쪽의 수보다 클 수 있음을 의미한다.
예를 들어, 33133의 경우,
부분문자열이 나타내는 수가 오름차순이 되도록 공백을 추가하여
가장 많은 부분문자열을 만들 수 있는 경우는 3, 3, 133,
또는 3, 31, 33이다.
그러나 첫 번째 조건에서 한 번의 예외를 둘 수 있으므로, 이를 고려하면
3, 3, 1, 3, 3이 된다.
부분문자열이 0으로 시작할 수 있음에 유의하라.
예를 들어, 103201을
1, 03, 201로 나눌 수 있고,
이 부분문자열들이 나타내는 수는 각각
1, 3, 201이다.
주어진 문자열에 대해 조건을 만족하며 부분문자열로 나눌 때, 부분문자열의 개수를 구하는 프로그램을 작성하라.
입력 형식
첫 줄에 문자열의 수를 나타내는 정수 가 주어진다. ()
이어지는 개의 줄에는 차례로 각 문자열에 대한 정보들이 주어진다.
개의 줄의 번째 줄에 번째 문자열의 길이를 나타내는 정수 가 주어진다. ()
개의 줄의 번째 줄에
번째 문자열이 주어진다.
이 문자열은 0부터 9까지 숫자로 이루어져 있다.
입력으로 주어지는 문자열의 길이 합, 즉, 는 을 넘지 않는다.
출력 형식
개의 줄에 걸쳐 답을 출력한다. 번째 줄에 번째 문자열을 조건을 만족하며 부분문자열로 나눌 때, 부분문자열의 개수를 출력한다.
예제
입력
2 5 33133 6 103201
출력
5 4
채점 방식
입력 케이스들은 다음과 같은 종류로 구별되며, 한 종류의 케이스를 다 맞혀야 그 종류에 배정된 점수를 받을 수 있다.
종류 1: 23점
;
종류 2: 31점
종류 3: 5점
문자열을 구성하는 숫자는 오름차순이다. 예: 03355, 22222
종류 4: 17점
문자열을 구성하는 숫자는 내림차순이다. 예: 999888, 210000
종류 5: 8점
문자열은 1부터 9까지 숫자로 이루어져 있다.
종류 6: 16점
추가적인 제한 조건이 없음.
해설
편의를 위해서, 주어진 문자열을 문자열 라고 하고, 문자열 의 번째 글자를 로, 원래 문자열의 번째 글자부터 번째 글자까지로 이루어진 문자열을 로 표기한다.
2차원 배열 이 있고 다음과 같이 정의하자.
이는 의 시간복잡도로 계산할 수 있다.
또한, 2차원 배열 가 있고 다음과 같이 정의하자.
각 에 대해 가능한 의 범위는 이상 이하이고, 번째 문자가 포함되는 부분문자열의 길이가 정확히 일 경우의 값이 이면, 이다.
정확히 인 경우의 값을 구하기 위해서, 와 가 나타내는 수를 비교해야 한다. 이때, 두 문자열의 길이가 같으므로, 문자열의 사전순 비교를 하면 된다. 미리 계산해둔 의 값을 활용하여, 사전순 비교를 수행한다. 사전순 비교를 수행했을 때, 가 나타내는 수가 가 나타내는 수보다 작거나 같은 경우, 이면서 인 k에 대해, 이다. 그렇지 않을 경우, 이다.
따라서 한 의 값을 구하는 시간복잡도는 이므로, 배열 의 모든 값을 구하는 시간복잡도는 이다.
비슷하게, 2차원 배열 가 있고 다음과 같이 정의하자.
배열 의 값을 구하는 것은 배열 의 값을 구하는 것과 비슷한 방식으로 가능하다. 시간복잡도는 이전과 같이 가 걸린다.
문제의 조건을 다르게 표현하면, 크기가 인 수열 가 있고, 이며, 를 만족하는 어떤 가 존재하는지를 의미한다.
따라서, 정답은 모든 에 대해 의 값 중 최댓값이라고 할 수 있다. 배열 와 배열 가 다 계산됐다면, 이는 의 시간복잡도로 구할 수 있다.
따라서, 이 문제를 해결하는 전체 시간복잡도는 이다.