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

C++의 문자열 변환을 위한 내부 알고리즘

<시간/>

주어진 문자열에 대해 짝수 위치에 있는 모든 요소를 ​​문자열의 끝으로 전송합니다. 요소를 전송하는 동안 모든 짝수 위치 및 홀수 위치 요소의 상대적 순서를 동일하게 유지하십시오.

예를 들어 주어진 문자열이 "a1b2c3d4e5f6g7h8i9j1k2l3m4"인 경우 O(n) 시간 복잡도에서 제자리에서 "abcdefghijklm1234567891234"로 변환합니다.

다음 단계

  • 3^k + 1 형식의 가장 높은 접두사 부분 문자열을 잘라냅니다. 이 단계에서는 3^k+1이 n(문자열 길이 )

  • 이 하위 문자열에 대해 인덱스 1, 3, 9……부터 시작하여 사이클 리더 반복 알고리즘(아래에 설명되어 있음)을 구현합니다. 사이클 리더 반복 알고리즘은 이 하위 문자열의 모든 항목을 올바른 위치로 전송합니다. 즉, 모든 알파벳은 하위 문자열의 왼쪽 절반으로 이동하고 모든 숫자는 이 하위 문자열의 오른쪽 절반으로 이동합니다. .

  • 단계 번호를 재귀적으로 구현하는 나머지 하위 문자열을 처리합니다. 1과 아니요. 2.

  • 현재로서는 처리된 하위 문자열을 함께 결합하기만 하면 됩니다. 끝에서 시작(예:왼쪽부터), 두 개의 하위 문자열을 선택하고 다음 단계를 구현하십시오. −

    • 첫 번째 부분 문자열의 후반부와 반대 방향 또는 반대 방향입니다.

    • 두 번째 하위 문자열의 전반부를 반대하거나 반대로 합니다.

    • 첫 번째 하위 문자열의 후반부와 두 번째 하위 문자열의 전반부를 함께 반대하거나 반대로 합니다.

  • 단계 번호를 반복합니다. 4 모든 하위 문자열이 결합될 때까지 및 제외됩니다. 첫 번째 하위 문자열이 두 번째 하위 문자열과 결합되는 k-way 병합과 동일합니다. 결과는 세 번째 등과 병합됩니다.

코드는 위의 알고리즘을 기반으로 아래에 제공됩니다 -

// C++ application of above approach
#include <bits/stdc++.h>
using namespace std;
// A utility function to swap characters void swap ( char* a1, char* b1 ) {
   char t = *a1; *a1 = *b1; *b1 = t;
}
// A utility function to reverse string str1[low1..high1]
void reverse ( char* str1, int low1, int high1 ) {
   while ( low < high ) {
      swap(&str1[low1], &str1[high1] ); ++low1; --high1;
   }
}
// Cycle leader algorithm to shift all even
// positioned elements at the end.
void cycleLeader ( char* str1, int shift1, int len1 ) {
   int j;
   char item1;
   for (int i = 1; i < len1; i *= 3 ) {
      j = i; item1 = str1[j + shift1];
      do{
         // odd index if ( j & 1 )
         j = len1 / 2 + j / 2;
         // even index or position else j /= 2;
         // keep the back-up of element at new index or position
         swap (&str1[j + shift1], &item1);
      }
   while ( j != i );
   }
}
// The main function to convert a string. This function
// mainly implements cycleLeader() to convert void moveNumberToSecondHalf( char* str1 ) {
   int k, lenFirst1; int lenRemaining1 = strlen( str1); int shift1 = 0;
   while ( lenRemaining1) {
      k = 0;
      // Step 1: Find the highest prefix
      // subarray of the form 3^k + 1
      while ( pow( 3, k ) + 1 <= lenRemaining1)
      k++; lenFirst1 = pow( 3, k - 1 ) + 1;
      lenRemaining1 -= lenFirst1;
      // Step 2: Implement cycle leader algorithm
      // for the highest subarray cycleLeader ( str1, shift1, lenFirst1 );
      // Step 4.1: Just opposite or reverse the second half of first subarray reverse ( str1,
         shift1/2, shift1 - 1 );
      // Step 4.2: Just opposite or reverse the first half of second sub-string. reverse ( str1,
         shift1, shift1 + lenFirst1 / 2 - 1 );
      // Step 4.3 Just opposite or reverse the second half of first sub-string and first half of
         second sub-string together reverse ( str1, shift1 / 2, shift1 + lenFirst1 / 2 - 1 );
      // Now increase the length of first subarray Shift1 += lenFirst1;
  }
}
// Driver program to verify or test above function int main() {
   char str1[] = "a1b2c3d4e5f6g7"; moveNumberToSecondHalf( str1 ); cout<<str1; return 0;
}

출력

abcdefg1234567