Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

อัลกอริทึมแบบแทนที่สำหรับการแปลงสตริงใน C++


สำหรับสตริงที่กำหนด ให้โอนองค์ประกอบที่มีตำแหน่งคู่ทั้งหมดไปยังจุดสิ้นสุดของสตริง ขณะถ่ายโอนองค์ประกอบ ให้รักษาลำดับสัมพัทธ์ขององค์ประกอบตำแหน่งคู่และตำแหน่งคี่เหมือนกัน

ตัวอย่างเช่น หากสตริงที่ระบุคือ "a1b2c3d4e5f6g7h8i9j1k2l3m4" ให้แปลงเป็น "abcdefghijklm1234567891234" ในตำแหน่งและความซับซ้อนของเวลา O(n)

มีขั้นตอนดังนี้

  • ตัดสตริงย่อยที่มีขนาดสูงสุดของแบบฟอร์ม 3^k + 1 ออก ในขั้นตอนนี้ เราจะหาจำนวนเต็มที่ไม่ติดลบ k สูงสุด โดยที่ 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