Computer >> Máy Tính >  >> Lập trình >> C ++

Một thuật toán tại chỗ cho Chuyển đổi chuỗi trong C ++

Đối với một chuỗi đã cho, hãy chuyển tất cả các phần tử có vị trí chẵn đến cuối chuỗi. Trong khi chuyển các phần tử, hãy giữ nguyên thứ tự tương đối của tất cả các phần tử có vị trí chẵn và lẻ.

Ví dụ:nếu chuỗi đã cho là "a1b2c3d4e5f6g7h8i9j1k2l3m4", hãy biến đổi nó thành "abcdefghijklm1234567891234" tại chỗ và theo độ phức tạp thời gian O (n).

Sau đây là các bước

  • Cắt bỏ chuỗi con có tiền tố cao nhất có kích thước là 3 ^ k + 1. Trong bước này, chúng tôi xác định vị trí số nguyên k âm cao nhất sao cho 3 ^ k + 1 nhỏ hơn hoặc bằng n (độ dài của chuỗi )

  • Thực hiện thuật toán lặp đầu chu kỳ (nó đã được giải thích bên dưới), bắt đầu với chỉ số 1, 3, 9 …… cho chuỗi con này. Thuật toán lặp trình dẫn đầu chu kỳ chuyển tất cả các mục của chuỗi con này đến vị trí chính xác của chúng, điều đó có nghĩa là, tất cả các bảng chữ cái được chuyển sang nửa bên trái của chuỗi con và tất cả các chữ số được chuyển sang nửa bên phải của chuỗi con này .

  • Xử lý chuỗi con còn lại thực hiện đệ quy các bước không. 1 và không. 2.

  • Hiện tại, chúng tôi chỉ yêu cầu nối các chuỗi con đã xử lý lại với nhau. Bắt đầu từ bất kỳ đầu nào (nói từ bên trái), chọn hai chuỗi con và thực hiện các bước sau -

    • Chỉ ngược lại hoặc đảo ngược nửa sau của chuỗi con đầu tiên.

    • Chỉ ngược lại hoặc đảo ngược nửa đầu của chuỗi con thứ hai.

    • Chỉ đối diện hoặc đảo ngược nửa sau của chuỗi con thứ nhất và nửa đầu của chuỗi phụ thứ hai với nhau.

  • Lặp lại bước không. 4 cho đến khi và trừ khi tất cả các chuỗi con được nối. Nó giống như hợp nhất k-way trong đó chuỗi con đầu tiên được nối với chuỗi thứ hai. Kết quả được hợp nhất với thứ ba, v.v.

Mã được đưa ra bên dưới dựa trên thuật toán trên -

// 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;
}

Đầu ra

abcdefg1234567