문제 소개
JavaScript 함수를 하나 작성해야 합니다. 이 함수는 첫 번째 인수로 문자열 str을, 두 번째 인수로 문자열 배열 arr을 전달받으며, str 안에서 arr에 포함된 하위 문자열을 찾아 여는 태그 <p>와 닫는 태그 </p> 한 쌍으로 감싸야 합니다.
단, 다음 두 가지 규칙을 반드시 지켜야 합니다.
- 두 하위 문자열이 서로 겹치는 경우에는 하나의 단락 태그 쌍으로 함께 감싼다.
- 태그로 감싸진 두 하위 문자열이 연속해서 나타나는 경우에도 하나로 합친다.
입력 및 출력 예시
예를 들어 입력 문자열과 배열이 다음과 같다고 가정해 보겠습니다.
const str = 'kkkllmm'; const arr = ["kkk","kkl","lm"];
이때 기대되는 출력 결과는 다음과 같습니다.
const output = '<p>kkkllm</p>m';
'kkk'와 'kkl'은 서로 겹치고, 바로 이어지는 'lm'까지 연속되므로 kkkllm 구간 전체가 하나의 <p> 태그로 묶이고, 마지막 'm'만 태그 밖에 남게 됩니다.
구현 코드
이 문제를 해결하는 JavaScript 코드는 다음과 같습니다.
const str = 'kkkllmm';
const arr = ["kkk","kkl","lm"];
var addParagraphTag = (str = [], arr = []) => {
if(!arr.length){
return str
};
const { length } = str;
let paraBoolean = new Array(length).fill(false);
let end = 0;
for (let i = 0; i < length; i++){
for (let j = 0; j < arr.length; j++){
let word = arr[j];
if (str.startsWith(word,i)) {
end = Math.max(end, i + word.length);
};
}
paraBoolean[i] = end > i;
};
let curr = 0;
let newStr = '';
while (curr < length) {
while(paraBoolean[curr] === false) {
newStr += str[curr++];
}
if (curr >= length) break;
newStr += '<p>';
let startBold = curr;
while (paraBoolean[curr] === true) curr++;
newStr += str.slice(startBold, curr);
newStr += '</p>';
};
return newStr;
};
console.log(addParagraphTag(str, arr));코드 동작 원리
핵심 아이디어는 문자열의 각 위치가 단락 태그로 감싸져야 하는지를 먼저 판별한 뒤, 연속된 구간을 하나의 블록으로 묶는 것입니다.
- 문자열 길이와 같은 크기의 불리언 배열 paraBoolean을 만들고 모두 false로 초기화합니다.
- 각 인덱스 i에서 시작하는 모든 단어를 startsWith()로 검사하여 매칭되면 end를 가장 먼 끝 위치로 갱신하고, paraBoolean[i]에 해당 위치가 태그 범위에 속하는지 저장합니다.
- 마지막으로 문자열을 순회하면서 paraBoolean이 false인 문자는 그대로 더하고, true인 연속 구간은 하나의 <p> ... </p> 블록으로 감싸 새로운 문자열을 완성합니다.
실행 결과
코드를 실행하면 콘솔에 다음과 같이 출력됩니다.
<p>kkkllm</p>m