알고리즘

C++ - DNA 조합 (2217) 백트래킹, 문자열

jun.s.gi 2023. 5. 23. 19:14
728x90

https://www.jungol.co.kr/bbs/board.php?bo_table=pbank&wr_id=1478&sca=3030 

 

JUNGOL

 

www.jungol.co.kr

 

1. check(붙여질 문자열, 붙일 문자열) -> 문자열이 붙어지면 붙여서 반환, 붙어지지 않으면 ""(빈 문자열)반환

2. rec(현재 DNA 상태, 깊이, 앞서 붙인 문자열) 

#pragma warning(disable:4996)
#include <stdio.h>
#include <string>
#include <iostream>
using namespace std;
int n, ans = 0x7fffffff;
string dna[10], temp;
int freq[10], swi;

string check(string s1, string s2)
{
	int idx = 0;
	int s1Len = (int)s1.size();
	int s2Len = (int)s2.size();

	// 짧은 것을 기준으로 합니다.
	int Length = s1Len < s2Len ? s1Len : s2Len;

	for (int i = 0; i < Length; i++)
	{
		// 붙여질 문자의 끝부분과 붙일 문자의 첫 부분이 맞으면 인덱스 저장
		if (s1.substr(s1Len - 1 - i, i + 1) == s2.substr(0, i + 1))
		{
			idx = s1Len - 1 - i;
			swi = 1;
		}
	}
	if (swi == 1)
		return s1.substr(0, idx) + s2;
	else
		return "";
}

void rec(string dnaStr, int depth, string rear)
{
	// 구해놓은 답보다 길이가 길다면 되돌아갑니다.
	if (ans <= (int)dnaStr.size()) return;

	if (depth >= n)
	{
		ans = (int)dnaStr.size();
		return;
	}

	for (int i = 0; i < n; i++)
	{
		if (freq[i]) continue;
		freq[i] = 1;

		// DNA 문자열이 비어있다면 현재 붙일 문자열을 그냥 인수로 사용합니다.
		if (dnaStr.empty() == 1)
			rec(dna[i], depth + 1, dna[i]);
		else
		{
			swi = 0;
			// 마지막으로 붙인 단어와 붙일 단어를 조합합니다.
			temp = check(rear, dna[i]);
			


			// 겹치는 부분이 없으면 그대로 붙여서 호출합니다.
			if (temp == "")
				rec(dnaStr + dna[i], depth + 1, dna[i]);

			// 겹치는 부분이 있다면 DNA 문자열에 구해놓은 문자열을 붙입니다. (중복 제거를 위해 )
			else
				rec(check(dnaStr, temp), depth + 1, dna[i]);

		}
		freq[i] = 0;
	}
}


int main()
{

	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> dna[i];

	rec("", 0, "");

	cout << ans;
	return 0;
}
728x90