给定一个字符串,我们需要找到获得同一字符串所需的最小旋转数。在这种情况下,我们将仅考虑左旋转。
例子:
Input : s = “geeks”
Output : 5
Input : s = “aaaa”
Output :1
天真的方法:基本的方法是从第一个位置开始旋转字符串,并计算转数,直到获得初始字符串为止。
高效方法:我们将遵循基本方法,但会尝试减少生成旋转所需的时间。
这个想法如下:
- 生成一个新字符串,其大小为输入字符串的两倍,如下所示:
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)。