Computer >> 컴퓨터 >  >> 프로그램 작성 >> C++

C++에서 DFA 기반 부문?

<시간/>

DFA(Deterministic Finite Automaton)는 숫자가 다른 숫자 k로 나누어 떨어지는지 여부를 확인하는 데 사용됩니다. 이 알고리즘은 숫자가 나누어지지 않는 경우 나머지도 찾을 수 있기 때문에 유용합니다.

DFA 기반 부서에서는 k 상태로 DFA 테이블을 작성합니다. DFA의 각 상태에는 0과 1만 있도록 숫자의 이진 표현을 고려합니다.

createTransTable(int k, int transTable[][2]) 함수는 transTable을 생성하고 그 안에 상태를 저장하는 데 사용됩니다. 그 수가 나누어질 수 있는 수 k와 2개의 열이 있는 배열인 transTable[][2]를 취합니다. 그런 다음 비트 0 다음 상태를 저장하는 두 개의 변수 trans_0과 비트 1 다음 상태를 저장하는 trans_1을 선언합니다.

void createTransTable(int k, int transTable[][2]){
   int trans_0, trans_1;

내부의 for 루프는 상태가 k보다 작을 때까지 실행됩니다. trans_0이 숫자 k보다 작으면 transTable[state][0]은 trans_0과 같으며 그렇지 않으면 k는 trans_0에서 뺍니다.

trans_1의 경우 trans_1이 k보다 작으면 transTable[state][1]은 trans_1과 같으며 그렇지 않으면 k는 trans_1에서 뺍니다.

for (int state = 0; state < k; state++){
   trans_0 = state << 1;
   transTable[state][0] = (trans_0 < k) ? trans_0 : trans_0 - k;
   trans_1 = (state << 1) + 1;
   transTable[state][1] = (trans_1 < k) ? trans_1 : trans_1 - k;
}

checkDivisible(int num, int &state, int transTable[][2]) 함수는 나눌 숫자, 참조에 의한 상태 변수 및 transTable[][2] 배열을 취합니다. 숫자가 0과 같지 않은지 확인한 다음 기본적으로 자신을 재귀적으로 호출하여 숫자가 0이 될 때까지 비트 오른쪽 시프트를 사용하여 왼쪽에서 오른쪽으로 숫자를 이동합니다. 오른쪽으로 이동하면 숫자가 0이 될 때까지 2로 나뉩니다. 그런 다음 transtable[state][num&1]이 상태 변수에 할당됩니다.

void checkDivisible(int num, int &state, int transTable[][2]){
   if (num != 0){
      checkDivisible(num >> 1, state, transTable);
      state = transTable[state][num&1];
   }
}

isDivisible(int num, int k) 함수는 피제수 수와 피제수 k를 취합니다. 2개의 열과 k개의 행을 갖는 전이 테이블 transTable[k][2]가 선언됩니다. 상태 변수를 수정하는 createTransTable(k, transTable) 및 checkDivisible(num, state, transTable)이 호출됩니다. 그런 다음 나눗셈에서 남은 나머지를 나타내는 상태 변수가 반환됩니다.

int isDivisible (int num, int k){
   int transTable[k][2];
   createTransTable(k, transTable);
   int state = 0;
   checkDivisible(num, state, transTable);
   return state;
}

예시

DFA 기반 부서에 대한 다음 구현을 살펴보겠습니다.

#include <bits/stdc++.h>
using namespace std;
void createTransTable(int k, int transTable[][2]){
   int trans_0, trans_1;
   for (int state = 0; state < k; state++){
      trans_0 = state << 1;
      transTable[state][0] = (trans_0 < k) ? trans_0 : trans_0 - k;
      trans_1 = (state << 1) + 1;
      transTable[state][1] = (trans_1 < k) ? trans_1 : trans_1 - k;
   }
}
void checkDivisible(int num, int &state, int transTable[][2]){
   if (num != 0){
      checkDivisible(num >> 1, state, transTable);
      state = transTable[state][num&1];
   }
}
int isDivisible (int num, int k){
   int transTable[k][2];
   createTransTable(k, transTable);
   int state = 0;
   checkDivisible(num, state, transTable);
   return state;
}
int main(){
   int num = 67;
   int k = 5;
   int remainder = isDivisible (num, k);
   if (remainder == 0)
      cout <<num<< " is divisible by "<<k;
   else
      cout <<num<< " is not divisible by "<<k<<" and lefts remainder "<<remainder;
   return 0;
}

출력

위의 코드는 다음과 같은 출력을 생성합니다.

67 is not divisible by 5 and lefts remainder 2