📌  相关文章
📜  检查两个字符串是否可以通过反转两个字符串的相等长度的子字符串来使它们相等

📅  最后修改于: 2021-10-26 05:49:46             🧑  作者: Mango

给定两个字符串S1S2 ,任务是检查是否可以通过从两个相等长度的字符串中反转子字符串来使字符串S1等于字符串S2

注意:一个子串可以反转任意次。

例子:

方法:

  1. 这个想法是通过对它们进行排序来使两个字符串相等。
  2. 首先,检查两个字符串是否具有相同的字符集。如果不是,那么答案是“否”。
  3. 将 substring 的长度固定为 reverse 为 2。现在,这意味着交换相邻字符。
  4. 现在,进行排序通过反转大小2的或者换句话说子串,交换相邻字符的字符串所需的移动次数,是字符串的反转次数。
  5. 如果两个字符串具有相同的反转计数,则答案为“是”。
  6. 如果它们具有不同的反转计数,则只有在至少满足以下条件之一时才能使它们相等:
    • 首先,如果反转计数的奇偶性相同,即偶数或奇数,则答案为“是”。我们将继续交换排序字符串中的任何一对元素,直到另一个元素被排序。由于反转计数的差异将是偶数,因此将任何对交换两次不会产生任何变化。
    • 第二,如果奇偶校验是不一样的,则必须有至少与任何所述字符串的频率大于1的一个字符。我们只会交换它们,直到另一个被排序。由于交换相同的字符不会做任何改变。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// function to count inversion
// count of the string
int inversionCount(string& s)
{
 
    // for storing frequency
    int freq[26] = { 0 };
    int inv = 0;
    for (int i = 0; i < s.length(); i++) {
        int temp = 0;
 
        // Add all the characters which
        // are less than the ith character
        // before i.
        for (int j = 0; j < int(s[i] - 'a'); j++)
            // adding the count to inversion
            // count
            temp += freq[j];
 
        inv += (i - temp);
        // updating the character in
        // the frequency array
 
        freq[s[i] - 'a']++;
    }
    return inv;
}
 
// function to check whether any
// of the string have a repeated
// character
bool haveRepeated(string& S1,
                string& S2)
{
 
    int freq[26] = { 0 };
    for (char i : S1) {
        if (freq[i - 'a'] > 0)
            return true;
        freq[i - 'a']++;
    }
 
    for (int i = 0; i < 26; i++)
        freq[i] = 0;
 
    for (char i : S2) {
        if (freq[i - 'a'] > 0)
            return true;
        freq[i - 'a']++;
    }
    return false;
}
 
// function to check whether the
// string S1 and S2 can be made
// equal by reversing sub strings
// of same size in both strings
void checkToMakeEqual(string S1,
                    string S2)
{
 
    // frequency array to check
    // whether both string have
    // same character or not
    int freq[26] = { 0 };
 
    for (int i = 0; i < S1.length(); i++) {
        // adding the frequency;
        freq[S1[i] - 'a']++;
    }
 
    bool flag = 0;
    for (int i = 0; i < S2.length(); i++) {
        if (freq[S2[i] - 'a'] == 0) {
            // if the character is not in S1
            flag = true;
            break;
        }
        // decrementing the frequency
        freq[S2[i] - 'a']--;
    }
 
    if (flag == true) {
        // If both string doesnot
        // have same characters or not
        cout << "No\n";
        return;
    }
 
    // finding inversion count
    // of both strings
    int invCount1 = inversionCount(S1);
    int invCount2 = inversionCount(S2);
 
    if (invCount1 == invCount2
        || (invCount1 & 1) == (invCount2 & 1)
        || haveRepeated(S1, S2)) {
        // If inversion count is same,
        // or have same parity or if
        // any of the string have a
        // repeated character then
        // the answer is Yes else No
        cout << "Yes\n";
    }
    else
        cout << "No\n";
}
 
// driver code
int main()
{
    string S1 = "abbca", S2 = "acabb";
    checkToMakeEqual(S1, S2);
    return 0;
}


Python3
# Python3 program for the above approach
 
# function to count inversion
# count of the string
def inversionCount(s):
     
    # for storing frequency
    freq = [0 for _ in range(26)]
    inv = 0
    for i in range(len(s)):
         
        # we'll add all the characters
        # which are less than the ith
        # character before i.
        temp = 0
        for j in range(ord(s[i]) - ord('a')):
             
            # adding the count to
            # inversion count
            temp += freq[j]
             
        inv += (i - temp)
         
        # updating the character in
        # the frequency array
        freq[ord(s[i]) - ord('a')] += 1
    return inv
 
# function to check whether
# any of the string have a
# repeated character
def haveRepeated(S1, S2):
    freq = [0 for _ in range(26)]
    for i in range(len(S1)):
        if freq[ord(S1[i]) - ord('a')] > 0:
            return 1
        freq[ord(S1[i]) - ord('a')] += 1
 
    for i in range(26):
        freq[i] = 0
 
    for i in range(len(S2)):
        if freq[ord(S2[i]) - ord('a')] > 0:
            return 1
        freq[ord(S2[i]) - ord('a')] += 1
 
    return 0
 
# function to check whether
# the string S1 and S2 can
# be made equal by reversing
# sub strings ofsame size in
# both strings
def checkToMakeEqual(S1, S2):
 
    # frequency array to check
    # whether both string have
    # same character or not
    freq = [0 for _ in range(26)]
 
    for i in range(len(S1)):
         
        # adding the frequency;
        freq[ord(S1[i]) - ord('a')] += 1
 
    flag = 0
    for i in range(len(S2)):
        if freq[ord(S2[i]) - ord('a')] == 0:
             
            # if the character is not in S1
            flag = 1
            break
             
        # decrementing the frequency
        freq[ord(S2[i]) - ord('a')] -= 1
     
    if flag == 1:
         
        # If both string does not
        # have same characters or not
        print("No")
        return
 
    # finding inversion count of
    # both strings
    invCount1 = inversionCount(S1)
    invCount2 = inversionCount(S2)
 
    if ((invCount1 == invCount2) or
       ((invCount1 % 2) == (invCount2 % 2)) or
         haveRepeated(S1, S2) == 1):
              
        # If inversion count is same,
        # or have same parity
        # or if any of the string
        # have a repeated character
        # then the answer is Yes else No
        print("Yes")
    else:
        print("No")
 
# Driver Code
S1 = "abbca"
S2 = "acabb"
 
checkToMakeEqual(S1, S2)


Java
// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG{
     
// Function to count inversion
// count of the string
static int inversionCount(String s)
{
     
    // For storing frequency
    int[] freq = new int[26];
    int inv = 0;
    for(int i = 0; i < s.length(); i++)
    {
        int temp = 0;
         
        // Add all the characters which
        // are less than the ith character
        // before i.
        for(int j = 0;
                j < (int)(s.charAt(i) - 'a');
                j++)
         
        // Adding the count to inversion
        // count
        temp += freq[j];
        inv += (i - temp);
         
        // Updating the character in
        // the frequency array
        freq[s.charAt(i) - 'a']++;
    }
    return inv;
}
 
// Function to check whether any
// of the string have a repeated
// character
static boolean haveRepeated(String S1,
                            String S2)
{
    int[] freq = new int[26];
    for(char i : S1.toCharArray())
    {
        if (freq[i - 'a'] > 0)
            return true;
        freq[i - 'a']++;
    }
     
    for(int i = 0; i < 26; i++)
        freq[i] = 0;
         
    for(char i : S2.toCharArray())
    {
        if (freq[i - 'a'] > 0)
            return true;
        freq[i - 'a']++;
    }
    return false;
}
 
// Function to check whether the
// string S1 and S2 can be made
// equal by reversing sub strings
// of same size in both strings
static void checkToMakeEqual(String S1,
                             String S2)
{
     
    // Frequency array to check
    // whether both string have
    // same character or not
    int[] freq = new int[26];
    for(int i = 0; i < S1.length(); i++)
    {
         
        // Adding the frequency;
        freq[S1.charAt(i) - 'a']++;
    }
     
    boolean flag = false;
    for(int i = 0; i < S2.length(); i++)
    {
        if (freq[S2.charAt(i) - 'a'] == 0)
        {
             
            // If the character is not in S1
            flag = true;
            break;
        }
         
        // Decrementing the frequency
        freq[S2.charAt(i) - 'a']--;
    }
     
    if (flag == true)
    {
         
        // If both string doesnot
        // have same characters or not
        System.out.println("No");
        return;
    }
     
    // Finding inversion count
    // of both strings
    int invCount1 = inversionCount(S1);
    int invCount2 = inversionCount(S2);
     
    if (invCount1 == invCount2 ||
       (invCount1 & 1) == (invCount2 & 1) ||
        haveRepeated(S1, S2))
    {
         
        // If inversion count is same,
        // or have same parity or if
        // any of the string have a
        // repeated character then
        // the answer is Yes else No
        System.out.println("Yes");
    }
    else
    System.out.println("No");
}
 
// Driver Code
public static void main (String[] args)
{
    String S1 = "abbca", S2 = "acabb";
     
    checkToMakeEqual(S1, S2);
}
}
 
// This code is contributed by offbeat


C#
// C# program for the above approach
using System;
class GFG{
     
// Function to count inversion
// count of the string
static int inversionCount(String s)
{
     
    // For storing frequency
    int[] freq = new int[26];
    int inv = 0;
    for(int i = 0; i < s.Length; i++)
    {
        int temp = 0;
         
        // Add all the characters which
        // are less than the ith character
        // before i.
        for(int j = 0;
                j < (int)(s[i] - 'a');
                j++)
         
        // Adding the count to inversion
        // count
        temp += freq[j];
        inv += (i - temp);
         
        // Updating the character in
        // the frequency array
        freq[s[i] - 'a']++;
    }
    return inv;
}
 
// Function to check whether any
// of the string have a repeated
// character
static bool haveRepeated(String S1,
                            String S2)
{
    int[] freq = new int[26];
    foreach(char i in S1.ToCharArray())
    {
        if (freq[i - 'a'] > 0)
            return true;
        freq[i - 'a']++;
    }
     
    for(int i = 0; i < 26; i++)
        freq[i] = 0;
         
    foreach(char i in S2.ToCharArray())
    {
        if (freq[i - 'a'] > 0)
            return true;
        freq[i - 'a']++;
    }
    return false;
}
 
// Function to check whether the
// string S1 and S2 can be made
// equal by reversing sub strings
// of same size in both strings
static void checkToMakeEqual(String S1,
                             String S2)
{
     
    // Frequency array to check
    // whether both string have
    // same character or not
    int[] freq = new int[26];
    for(int i = 0; i < S1.Length; i++)
    {
         
        // Adding the frequency;
        freq[S1[i] - 'a']++;
    }
     
    bool flag = false;
    for(int i = 0; i < S2.Length; i++)
    {
        if (freq[S2[i] - 'a'] == 0)
        {
             
            // If the character is not in S1
            flag = true;
            break;
        }
         
        // Decrementing the frequency
        freq[S2[i] - 'a']--;
    }
     
    if (flag == true)
    {
         
        // If both string doesnot
        // have same characters or not
        Console.WriteLine("No");
        return;
    }
     
    // Finding inversion count
    // of both strings
    int invCount1 = inversionCount(S1);
    int invCount2 = inversionCount(S2);
     
    if (invCount1 == invCount2 ||
       (invCount1 & 1) == (invCount2 & 1) ||
        haveRepeated(S1, S2))
    {
         
        // If inversion count is same,
        // or have same parity or if
        // any of the string have a
        // repeated character then
        // the answer is Yes else No
        Console.WriteLine("Yes");
    }
    else
    Console.WriteLine("No");
}
 
// Driver Code
public static void Main(String[] args)
{
    String S1 = "abbca", S2 = "acabb";
     
    checkToMakeEqual(S1, S2);
}
}
 
// This code is contributed by gauravrajput1


Javascript


输出:
Yes

时间复杂度:

O(N)
空间复杂度:
O(1)