📌  相关文章
📜  获得相同String所需的最小旋转次数|套装2

📅  最后修改于: 2021-05-04 10:51:58             🧑  作者: Mango

给定一个字符串,我们需要找到获得同一字符串所需的最小旋转数。在这种情况下,我们将仅考虑左旋转。

例子:

天真的方法:基本的方法是从第一个位置开始旋转字符串,并计算转数,直到获得初始字符串为止。

高效方法:我们将遵循基本方法,但会尝试减少生成旋转所需的时间。
这个想法如下:

  • 生成一个新字符串,其大小为输入字符串的两倍,如下所示:
newString = original string excluding first character 
            + original string with the first character.

+ denotes concatenation here.  
  • 如果原始字符串为str =“ abcd”,则新字符串将为“ bcdabcd”。
  • 现在,任务仍然是在新生成的字符串搜索原始字符串,并在所需转数中找到该字符串的索引。
  • 对于字符串匹配,我们将使用KMP算法,该算法在线性时间内执行字符串匹配。

下面是上述方法的实现:

C++
// C++ implementation of the above approach
#include 
using namespace std;
void computeLPSArray(char* pat, int M, int* lps);
  
// Prints occurrences of txt[] in pat[]
int KMPSearch(char* pat, char* txt)
{
    int M = strlen(pat);
    int N = strlen(txt);
  
    // Create lps[] that will hold the longest
    // prefix suffix values for pattern
    int lps[M];
  
    // Preprocess the pattern (calculate lps[] array)
    computeLPSArray(pat, M, lps);
  
    // Index for txt[] , // index for pat[]
    int i = 0;
    int j = 0;
    while (i < N) {
        if (pat[j] == txt[i]) {
            j++;
            i++;
        }
  
        if (j == M) {
            return i - j;
            j = lps[j - 1];
        }
  
        // Mismatch after j matches
        else if (i < N && pat[j] != txt[i]) {
 
            // Do not match lps[0..lps[j-1]] characters,
            // they will match anyway
            if (j != 0)
                j = lps[j - 1];
            else
                i = i + 1;
        }
    }
}
  
// Fills lps[] for given patttern pat[0..M-1]
void computeLPSArray(char* pat, int M, int* lps)
{
    // Length of the previous longest prefix suffix
    int len = 0;
     
    // lps[0] is always 0
    lps[0] = 0;
  
    // The loop calculates lps[i] for i = 1 to M-1
    int i = 1;
    while (i < M) {
        if (pat[i] == pat[len]) {
            len++;
            lps[i] = len;
            i++;
        }
 
        // (pat[i] != pat[len])
        else
        {
            // This is tricky. Consider the example.
            // AAACAAAA and i = 7. The idea is similar
            // to search step.
            if (len != 0) {
                len = lps[len - 1];
            }
            else
            {
                lps[i] = 0;
                i++;
            }
        }
    }
}
 
// Returns count of rotations to get the
// same string back
int countRotations(string s)
{
    // Form a string excluding the first character
    // and concatenating the string at the end
    string s1 = s.substr(1, s.size() - 1) + s;
  
    // Convert the string to character array
    char pat[s.length()], text[s1.length()];
  
    strcpy(pat, s.c_str());
    strcpy(text, s1.c_str());
  
    // Use the KMP search algorithm
    // to find it in O(N) time
    return 1 + KMPSearch(pat, text);
}
  
// Driver code
int main()
{
    string s1 = "geeks";
  
    cout << countRotations(s1);
  
    return 0;
}


Java
// Java implementation of the above approach
class GFG
{
 
// Prints occurrences of txt[] in pat[]
static int KMPSearch(char []pat, char []txt)
{
    int M = pat.length;
    int N = txt.length;
  
    // Create lps[] that will hold the longest
    // prefix suffix values for pattern
    int lps[] = new int[M];
  
    // Preprocess the pattern (calculate lps[] array)
    computeLPSArray(pat, M, lps);
  
    // Index for txt[] , // index for pat[]
    int i = 0;
    int j = 0;
    while (i < N)
    {
        if (pat[j] == txt[i])
        {
            j++;
            i++;
        }
  
        if (j == M)
        {
            return i - j + 1;
            //j = lps[j - 1];
        }
  
        // Mismatch after j matches
        else if (i < N && pat[j] != txt[i])
        {
 
            // Do not match lps[0..lps[j-1]] characters,
            // they will match anyway
            if (j != 0)
                j = lps[j - 1];
            else
                i = i + 1;
        }
    }
    return 0;
}
  
// Fills lps[] for given patttern pat[0..M-1]
static void computeLPSArray(char []pat, int M, int []lps)
{
   
    // Length of the previous longest prefix suffix
    int len = 0;
     
    // lps[0] is always 0
    lps[0] = 0;
  
    // The loop calculates lps[i] for i = 1 to M-1
    int i = 1;
    while (i < M)
    {
        if (pat[i] == pat[len])
        {
            len++;
            lps[i] = len;
            i++;
        }
 
        // (pat[i] != pat[len])
        else
        {
            // This is tricky. Consider the example.
            // AAACAAAA and i = 7. The idea is similar
            // to search step.
            if (len != 0) {
                len = lps[len - 1];
            }
            else
            {
                lps[i] = 0;
                i++;
            }
        }
    }
}
 
// Returns count of rotations to get the
// same String back
static int countRotations(String s)
{
    // Form a String excluding the first character
    // and concatenating the String at the end
    String s1 = s.substring(1, s.length() - 1) + s;
  
    // Convert the String to character array
    char []pat = s.toCharArray();
    char []text = s1.toCharArray();
  
    // Use the KMP search algorithm
    // to find it in O(N) time
    return 1 + KMPSearch(pat, text);
}
  
// Driver code
public static void main(String []args)
{
    String s1 = "geeks";
    System.out.print(countRotations(s1));
}
}
 
// This code is contributed by rutvik_56.


Python3
# Python3 implementation of the above approach
 
# Prints occurrences of txt[] in pat[]
def KMPSearch(pat, txt):
 
    M = len(pat)
    N = len(txt)
 
    # Create lps[] that will hold the longest
    # prefix suffix values for pattern
    lps = [0] * M
 
    # Preprocess the pattern (calculate lps[] array)
    computeLPSArray(pat, M, lps)
 
    # Index for txt[] , # index for pat[]
    i = 0
    j = 0
    while i < N:
        if pat[j] == txt[i]:
            j += 1
            i += 1
 
        if j == M:
            return i - j
            j = lps[j - 1]
 
        # Mismatch after j matches
        elif i < N and pat[j] != txt[i]:
 
            # Do not match lps[0..lps[j-1]] characters,
            # they will match anyway
            if j != 0:
                j = lps[j - 1]
            else:
                i = i + 1
 
# Fills lps[] for given patttern pat[0..M-1]
def computeLPSArray(pat, M, lps):
     
    # Length of the previous longest prefix suffix
    _len = 0
     
    # lps[0] is always 0
    lps[0] = 0
 
    # The loop calculates lps[i] for i = 1 to M-1
    i = 1
    while i < M:
        if pat[i] == pat[_len]:
            _len += 1
            lps[i] = _len
            i += 1
 
        # (pat[i] != pat[_len])
        else:
         
            # This is tricky. Consider the example.
            # AAACAAAA and i = 7. The idea is similar
            # to search step.
            if _len != 0:
                _len = lps[_len - 1]
            else:
                lps[i] = 0
                i += 1
 
# Returns count of rotations to get the
# same string back
def countRotations(s):
 
    # Form a string excluding the first character
    # and concatenating the string at the end
    s1 = s[1 : len(s)] + s
 
    # Convert the string to character array
    pat = s[:]
    text = s1[:]
 
    # Use the KMP search algorithm
    # to find it in O(N) time
    return 1 + KMPSearch(pat, text)
 
# Driver code
s1 = "geeks"
print(countRotations(s1))
 
# This code is contributed by divyamohan123


C#
// C# implementation of the above approach
using System;
 
class GFG{
 
// Prints occurrences of txt[] in pat[]
static int KMPSearch(char []pat, char []txt)
{
    int M = pat.Length;
    int N = txt.Length;
  
    // Create lps[] that will hold the longest
    // prefix suffix values for pattern
    int []lps = new int[M];
  
    // Preprocess the pattern (calculate lps[] array)
    computeLPSArray(pat, M, lps);
  
    // Index for txt[] , // index for pat[]
    int i = 0;
    int j = 0;
     
    while (i < N)
    {
        if (pat[j] == txt[i])
        {
            j++;
            i++;
        }
  
        if (j == M)
        {
            return i - j ;
            //j = lps[j - 1];
        }
  
        // Mismatch after j matches
        else if (i < N && pat[j] != txt[i])
        {
             
            // Do not match lps[0..lps[j-1]]
            // characters, they will match anyway
            if (j != 0)
                j = lps[j - 1];
            else
                i = i + 1;
        }
    }
    return 0;
}
  
// Fills lps[] for given patttern pat[0..M-1]
static void computeLPSArray(char []pat, int M,
                            int []lps)
{
     
    // Length of the previous longest
    // prefix suffix
    int len = 0;
     
    // lps[0] is always 0
    lps[0] = 0;
  
    // The loop calculates lps[i]
    // for i = 1 to M-1
    int i = 1;
     
    while (i < M)
    {
        if (pat[i] == pat[len])
        {
            len++;
            lps[i] = len;
            i++;
        }
 
        // (pat[i] != pat[len])
        else
        {
             
            // This is tricky. Consider the example.
            // AAACAAAA and i = 7. The idea is similar
            // to search step.
            if (len != 0) {
                len = lps[len - 1];
            }
            else
            {
                lps[i] = 0;
                i++;
            }
        }
    }
}
 
// Returns count of rotations to get the
// same string back
static int countRotations(string s)
{
     
    // Form a string excluding the first character
    // and concatenating the string at the end
    string s1 = s.Substring(1, s.Length - 1) + s;
  
    // Convert the string to character array
    char []pat = s.ToCharArray();
    char []text = s1.ToCharArray();
  
    // Use the KMP search algorithm
    // to find it in O(N) time
    return 1 + KMPSearch(pat, text);
}
  
// Driver code
public static void Main(params string []args)
{
    string s1 = "geeks";
     
    Console.Write(countRotations(s1));
}
}
 
// This code is contributed by pratham76


输出:
5

时间复杂度: O(N)。