透過僅設定一個大小為 K 的子字串的位來最小化二進位制字串中的漢明距離


兩個等長字串之間的漢明距離是在所有位置上,一個字串在對應位置上與另一個字串具有不同值的個數。我們可以透過以下示例來理解這一點:

S = “ramanisgoing”
T = “dishaisgoing”

這裡,5 是兩個字串 S 和 T 之間的漢明距離,因為 raman 和 disha 是兩個單詞,它們使字串發生變化以變得相等。

問題陳述

然而,在這個問題中,我們需要找到兩個僅包含二進位制數字的字串之間的漢明距離。一個字串將由使用者提供,例如 S,另一個字串,例如 T,並且最初,我們將假設它只包含“0”位,並且其大小與給定字串的大小相同。我們將得到一個數字“k”,其值將表示一個子字串可以包含的元素個數,這些元素僅包含 1 作為其元素,以便我們將該大小為 k 的子字串放在我們字串 (T) 的任何位置,以最小化兩個子字串 S 和 T 之間的漢明距離。

讓我們嘗試藉助一些示例來理解這個問題。

輸入

S = "100111”   K = 5

輸出

3

解釋

由於初始字串 T 將等於“000000”,並且字串 T 將更改為與字串 S 進行比較,以在 k=5 時找到最小漢明距離,如下所示:“111110”和“011111”。

100111 和 000000 將給出 4 作為它們的漢明距離。100111 和 111110 將為我們提供 3 作為它們的漢明距離,而 100111 和 011111 將給出 3 作為它們的漢明距離。

但最小漢明距離將為 3,因為 3 小於 4。因此,3 是我們的答案。

 − S = "100101”	 K = 5
 − 3

由於初始字串 T 將等於“000000”,並且字串 T 將更改為與字串 S 進行比較,以在 k=5 時找到最小漢明距離,如下所示:“111110”和“011111”。

100101 和 000000 將給出 3 作為它們的漢明距離。100101 和 111110 將為我們提供 4 作為它們的漢明距離,而 100101 和 011111 將給出 4 作為它們的漢明距離。

但最小漢明距離將為 3,因為 3 小於 4。因此,3 是我們的答案。

問題解釋

讓我們嘗試理解問題並找到它的解決方案。

方法 1:暴力解法

我們將透過更改子字串在不同初始點和結束點的位置來更改字串 T,以便我們可以在所有可能的字串中獲得最小的漢明距離。

示例

以下是各種程式語言中暴力解法的實現:

#include <stdio.h>
#include <string.h>
// Function to get minimum hamming distance through iteration
int helper(char* S, int k) {
   // n is the size of the string
   int n = strlen(S);
   // Take another string T and initiate it with zero bits size equal to that of S
   char T[n+1];
   memset(T, '0', sizeof(T));
   T[n] = '\0';
   // Take another string v to initiate it same as T
   char v[n+1];
   memset(v, '0', sizeof(v));
   v[n] = '\0';
   // Define mini as the hamming distance between T and S
   int mini = 0;
   int l = 0;
   while (l < n) {
      if (S[l] != T[l])
      mini++;
      l++;
   }
   for (int i = 0; i < n - k + 1; i++) {
      int j = 0, a = 0, l = 0;
      // Alter string v by changing bits of size k
      while (j < k) {
         v[j + i] = '1';
         j++;
      }
      // Calculate hamming distance
      while (l < n) {
         if (S[l] != v[l])
            a++;
         l++;
      }
      // Check if the previous hamming distance is greater than the current hamming distance, if yes, then replace that distance element
      if (mini > a) {
         mini = a;
      }
      // Again assign v as the T string
      strcpy(v, T);
   }
   // Return the minimum hamming distance found through the above iterations
   return mini;
}
int main() {
   // Give input string S
   char S[] = "100101";
   // Give the value of k that is the substring size
   int K = 5;
   // Call the helper function
   printf("The minimum hamming distance is: %d\n", helper(S, K));
   return 0;
}

輸出

The minimum hamming distance is: 3
#include <bits/stdc++.h>
using namespace std;
// Make a function to get minimum hamming distance through iteration
int helper(string S,int k){
   // n is the size of the string
   int n=S.size();
   // Take another string T and initiate it with zero bits size equal to that of S
   string T;
   for(int i=0; i<n; i++) {
      T+="0";
   }
   // Take another string v to initiate it same as T
   string v=T;
   // Define mini as the hamming distance between T and S
   int mini=0;
   int l=0;
   while(l<n) {
      if(S[l]!=T[l])mini++;
      l++;
   }
   for(int i=0; i<n-k+1; i++) {
      int j=0,a=0,l=0;
      // alter string v by changing bits of size k
      while(j<k) {
         v[j+i]='1';
         j++;
      }
      // calculate hamming distance
      while(l<n) {
         if(S[l]!=v[l])a++;
         l++;
      }
      // Check if the previous hamming distance is greater than the current hamming distance, if yes then replace that distance element
      if(mini>a) {
         mini=a;
      }
      // Again assign v as the T string
      v=T;
   }
   // return the minimum hamming distance found through the above iterations
   return mini;
}
int main(){
   // Give input string S
   string S = "100101";
   // Give the value of k that is the substring size
   int K = 5;
   // Call the helper function
   cout << "The minimum hamming distance is: "<< helper(S,K);
   return 0;
}

輸出

The minimum hamming distance is: 3
public class Main {
   // Function to get minimum hamming distance through iteration
   static int helper(String S, int k) {
      // n is the size of the string
      int n = S.length();
      // Take another string T and initiate it with zero bits size equal to that of S
      StringBuilder T = new StringBuilder();
      for (int i = 0; i < n; i++) {
         T.append('0');
      }
      // Take another string v to initiate it same as T
      StringBuilder v = new StringBuilder(T);
      // Define mini as the hamming distance between T and S
      int mini = 0;
      int l = 0;
      while (l < n) {
         if (S.charAt(l) != T.charAt(l))
         mini++;
         l++;
      }
      for (int i = 0; i < n - k + 1; i++) {
         int j = 0, a = 0;
         // Alter string v by changing bits of size k
         while (j < k) {
            v.setCharAt(j + i, '1');
            j++;
         }
         // Calculate hamming distance
         l = 0; // Reinitialize l
         while (l < n) {
            if (S.charAt(l) != v.charAt(l))
            a++;
            l++;
         }
         // Check if the previous hamming distance is greater than the current hamming distance, if yes, then replace that distance element
         if (mini > a) {
            mini = a;
         }
         // Again assign v as the T string
         v = new StringBuilder(T);
      }
      // Return the minimum hamming distance found through the above iterations
      return mini;
   }

   public static void main(String[] args) {
      // Give input string S
      String S = "100101";
      // Give the value of k that is the substring size
      int K = 5;
      // Call the helper function
      System.out.println("The minimum hamming distance is: " + helper(S, K));
   }
}

輸出

The minimum hamming distance is: 3
def helper(S, k):
   n = len(S)
   # Take another string T and initiate it with zero bits size equal to that of S
   T = '0' * n
   # Take another string v to initiate it same as T
   v = T
   # Define mini as the hamming distance between T and S
   mini = 0
   l = 0
   while l < n:
      if S[l] != T[l]:
         mini += 1
      l += 1
   for i in range(n - k + 1):
      j, a, l = 0, 0, 0
      # Alter string v by changing bits of size k
      while j < k:
         v = v[:j + i] + '1' + v[j + i + 1:]
         j += 1
      # Calculate hamming distance
      while l < n:
         if S[l] != v[l]:
         a += 1
         l += 1
      # Check if the previous hamming distance is greater than the current hamming distance, if yes, then replace that distance element
      if mini > a:
         mini = a
      # Again assign v as the T string
      v = T
   # Return the minimum hamming distance found through the above iterations
   return mini

# Give input string S
S = "100101"
# Give the value of k that is the substring size
K = 5
# Call the helper function
print("The minimum hamming distance is:", helper(S, K))

輸出

The minimum hamming distance is: 3

方法 2:最佳化解法

演算法

  • 使用字首和陣列計算存在的 1 的個數,並將其儲存為我們的最小漢明距離

  • 遍歷 S 字串以查詢字串 S 中 K 個不同子字串之間 1 的值。

  • 如果 (i-1<0) 將值 v 作為 arr[i+K-1],否則,將值 v 作為 (arr[i+K-1]-arr[i-1])

  • 透過找到先前漢明距離和當前漢明距離之間的最小值來儲存最小值。

  • 當前漢明距離可以透過對來自 K 個子字串的零元素個數 (K - v) 和當前 S 子字串中存在的零元素個數 (cnt - v) 的加法進行操作來找到

  • 最後,返回總的最小距離。

示例

以下是各種程式語言中最佳化解法的實現:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Make a helper function to get minimum hamming distance through iteration
int helper(char *S, int K){
// n is the size of the string
   int n = strlen(S);
   // initialize an array of size 'n'
   int arr[n];
   if(S[0]=='0')arr[0]=0;
   else arr[0]=1;
   // Count the number of 1's in the string S
   for (int i = 1; i < n; i++) {
      if(S[i]=='0')arr[i]=arr[i-1];
      else arr[i]=arr[i-1]+1;
   }
   int cnt = arr[n - 1];
   // Define mini as the hamming distance between T and S
   int mini = cnt;
   // Traverse through S to find the minimum
   for (int i = 0; i < n - K; i++) {
      int v;
      if(i-1==-1)v=arr[i+K-1];
      else v= arr[i+K-1]-arr[i-1];
      // Store the minimum
      if (cnt - v + (K - v) < mini)
         mini = cnt - v + (K - v);
   }
   // Return the minimum hamming distance
   return mini;
}
int main(){
   // Give input string S
   char *S = "100101";
   // Give the value of k that is the substring size
   int K = 5;
   // Call the helper function
   printf("The minimum hamming distance is: %d", helper(S,K));
   return 0;
}

輸出

The minimum hamming distance is: 3
#include <bits/stdc++.h>
using namespace std;
// Make a helper function to get minimum hamming distance through iteration
int helper(string S, int K){
// n is the size of the string
   int n = S.size();
   // initialize an array of size 'n'
   int arr[n];
   if(S[0]=='0')arr[0]=0;
   else arr[0]=1;
   // Count the number of 1's in the string S
   for (int i = 1; i < n; i++) {
      if(S[i]=='0')arr[i]=arr[i-1];
      else arr[i]=arr[i-1]+1;
   }
   int cnt = arr[n - 1];
   // Define mini as the hamming distance between T and S
   int mini = cnt;
   // Traverse through S to find the minimum
   for (int i = 0; i < n - K; i++) {
      int v;
      if(i-1==-1)v=arr[i+K-1];
      else v= arr[i+K-1]-arr[i-1];
      // Store the minimum
      mini = min(mini, cnt - v + (K - v));
   }
   // Return the minimum hamming distance
   return mini;
}
int main(){
   // Give input string S
   string S = "100101";
   // Give the value of k that is the substring size
   int K = 5;
   // Call the helper function
   cout << "The minimum hamming distance is: "<< helper(S,K);
   return 0;
}

輸出

The minimum hamming distance is: 3
public class Main {
   // Make a helper function to get the minimum hamming distance through iteration
   static int helper(String S, int K) {
      // n is the size of the string
      int n = S.length();
      
      // Initialize an array of size 'n'
      int[] arr = new int[n];
      if (S.charAt(0) == '0') {
         arr[0] = 0;
      } else {
         arr[0] = 1;
      }
      // Count the number of 1's in the string S
      for (int i = 1; i < n; i++) {
         if (S.charAt(i) == '0') {
            arr[i] = arr[i - 1];
         } else {
            arr[i] = arr[i - 1] + 1;
         }
      }
      int cnt = arr[n - 1];
      // Define mini as the hamming distance between T and S
      int mini = cnt;
      
      // Traverse through S to find the minimum
      for (int i = 0; i < n - K; i++) {
         int v;
         if (i - 1 == -1) {
            v = arr[i + K - 1];
         } else {
            v = arr[i + K - 1] - arr[i - 1];
         }

         // Store the minimum
         mini = Math.min(mini, cnt - v + (K - v));
      }
      // Return the minimum hamming distance
      return mini;
   }
   public static void main(String[] args) {
      // Give input string S
      String S = "100101";
      // Give the value of K, which is the substring size
      int K = 5;
      // Call the helper function
      System.out.println("The minimum hamming distance is: " + helper(S, K));
   }
}

輸出

The minimum hamming distance is: 3
def helper(S, K):
   # n is the size of the string
   n = len(S)

   # Initialize an array of size 'n'
   arr = [0] * n
   # Initialize the first element of the array based on the first character of S
   if S[0] == '0':
      arr[0] = 0
   else:
        arr[0] = 1
   # Count the number of 1's in the string S
   for i in range(1, n):
      if S[i] == '0':
         arr[i] = arr[i - 1]
      else:
         arr[i] = arr[i - 1] + 1

   # Calculate the total count of 1's in the string
   cnt = arr[n - 1]

   # Initialize mini as the total count
   mini = cnt
   # Traverse through S to find the minimum hamming distance
   for i in range(n - K):
      v = 0
      # Calculate the difference in counts for the sliding window
      if i - 1 == -1:
         v = arr[i + K - 1]
      else:
         v = arr[i + K - 1] - arr[i - 1]
      # Update mini with the minimum hamming distance
      mini = min(mini, cnt - v + (K - v))

   # Return the minimum hamming distance
   return mini
# Input string S
S = "100101"
# Value of K, which is the substring size
K = 5
# Call the helper function and display the result
print("The minimum hamming distance is:", helper(S, K))

輸出

The minimum hamming distance is: 3

結論

在本文中,為了找到最小漢明距離,我們將首先看到一種樸素的方法,但為了提高其時間複雜度,我們將使用字首和陣列的概念,透過該概念,我們可以在一個迴圈中避免在不同迴圈中重複計數。

更新於: 2024-01-22

瀏覽量 135 次

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告