Find minimum shift for longest common prefix

You are given two string str1 and str2 of same length. In a single shift you can rotate one string (str2) by 1 element such that its 1st element becomes the last and second one becomes the first like “abcd” will change to “bcda” after one shift operation. You have to find the minimum shift operation required to get common prefix of maximum length from str1 and str2.

Examples:

Input : str1[] = "geeks", 
        str2 = "dgeek"
Output : Shift = 1, 
         Prefix = geek

Input : str1[] = "practicegeeks",
        str2 = "coderpractice"
Output : Shift = 5
         Prefix = practice

Naive Approach : Shift second string one by one and keep track the length of longest prefix for each shift, there are total of n shifts and for each shift finding the length of common prefix will take O(n) time. Hence, overall time complexity for this approach is O(n^2).
Better Approach : If we will add second string at the end of itself that is str2 = str2 + str2 then there is no need of finding prefix for each shift separately. Now, after adding str2 to itself we have to only find the longest prefix of str1 present in str2 and the starting position of that prefix in str2 will give us the actual number of shift required. For finding longest prefix we can use KMP pattern search algorithm.
So, in this way our time-complexity will reduces to O(n) only.

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP program to find longest common prefix
// after rotation of second string.
#include <bits/stdc++.h>
using namespace std;
  
// function for KMP search
void KMP(int m, int n, string str2, string str1)
{
    int pos = 0, len = 0;
  
    // preprocessing of longest proper prefix
    int p[m + 1];
    int k = 0;
    p[1] = 0;
  
    for (int i = 2; i <= n; i++) {
        while (k > 0 && str1[k] != str1[i - 1])
            k = p[k];
        if (str1[k] == str1[i - 1])
            ++k;
        p[i] = k;
    }
  
    // find out the longest prefix and position
    for (int j = 0, i = 0; i < m; i++) {
        while (j > 0 && str1[j] != str2[i])
            j = p[j];
        if (str1[j] == str2[i])
            j++;
  
        // for new position with longer prefix in str2
        // update pos and len
        if (j > len) {
            len = j;
            pos = i - j + 1;
        }
    }
  
    // print result
    cout << "Shift = " << pos << endl;
    cout << "Prefix = " << str1.substr(0, len);
}
  
// driver function
int main()
{
    string str1 = "geeksforgeeks";
    string str2 = "forgeeksgeeks";
    int n = str1.size();
    str2 = str2 + str2;
    KMP(2 * n, n, str2, str1);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find longest common prefix
// after rotation of second string.
  
class GFG {
  
    // function for KMP search
    static void KMP(int m, int n, 
                    String str2, String str1)
    {
        int pos = 0, len = 0;
        int []p = new int[m + 1];
        int k = 0;
  
        //p[1] = 0;
        char []ch1 = str1.toCharArray();
        char []ch2 = str2.toCharArray();
  
        for (int i = 2; i <= n; i++)
        {
            while (k > 0 && ch1[k] != ch1[i - 1])
                k = p[k];
            if (ch1[k] == ch1[i - 1])
                ++k;
            p[i] = k;
        }
  
        // find out the longest prefix and position
        for (int j = 0, i = 0; i < m; i++) 
        {
            while (j > 0 && j < n && ch1[j] != ch2[i])
                j = p[j];
            if (j < n && ch1[j] == ch2[i])
                j++;
      
            // for new position with longer prefix in str2
            // update pos and len
            if (j > len)
            {
                len = j;
                pos = i - j + 1;
            }
        }
  
            // print result
            System.out.println("Shift = " + pos);
            System.out.println("Prefix = "
                                str1.substring(0,len));
        }
  
    // Driver code
    public static void main(String[] args) 
    {
        String str1 = "geeksforgeeks";
        String str2 = "forgeeksgeeks";
        int n = str1.length();
        str2 = str2 + str2;
        KMP(2 * n, n, str2, str1);
    }
}
  
// This code is contributed by Ita_c.

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to find longest common prefix
# after rotation of second string.
  
# function for KMP search
def KMP(m, n, str2, str1):
  
    pos = 0
    Len = 0
  
    # preprocessing of longest proper prefix
    p = [0 for i in range(m + 1)]
    k = 0
  
    for i in range(2, n + 1): 
        while (k > 0 and str1[k] != str1[i - 1]):
            k = p[k]
        if (str1[k] == str1[i - 1]):
            k += 1
        p[i] = k
      
  
    # find out the longest prefix and position
    j = 0
    for i in range(m):
        while (j > 0 and j < n and str1[j] != str2[i]):
            j = p[j]
        if (j < n and str1[j] == str2[i]):
            j += 1
   
        # for new position with longer prefix 
        # in str2 update pos and Len
        if (j > Len): 
            Len = j
            pos = i - j + 1
          
    # prresult
    print("Shift = ", pos)
    print("Prefix = ", str1[:Len])
  
# Driver Code
str1 = "geeksforgeeks"
str2 = "forgeeksgeeks"
n = len(str1)
str2 = str2 + str2
KMP(2 * n, n, str2, str1)
      
# This code is contributed by Mohit kumar 29

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to find longest common prefix
// after rotation of second string.
using System;
      
class GFG {
   
    // function for KMP search
    static void KMP(int m, int n, 
                    String str2, String str1)
    {
        int pos = 0, len = 0;
        int []p = new int[m + 1];
        int k = 0;
   
        //p[1] = 0;
        char []ch1 = str1.ToCharArray();
        char []ch2 = str2.ToCharArray();
   
        for (int i = 2; i <= n; i++)
        {
            while (k > 0 && ch1[k] != ch1[i - 1])
                k = p[k];
            if (ch1[k] == ch1[i - 1])
                ++k;
            p[i] = k;
        }
   
        // find out the longest prefix and position
        for (int j = 0, i = 0; i < m; i++) 
        {
            while (j > 0 && j < n && ch1[j] != ch2[i])
                j = p[j];
            if (j < n && ch1[j] == ch2[i])
                j++;
       
            // for new position with longer prefix in str2
            // update pos and len
            if (j > len)
            {
                len = j;
                pos = i - j + 1;
            }
        }
   
            // print result
            Console.WriteLine("Shift = " + pos);
            Console.WriteLine("Prefix = "
                                str1.Substring(0,len));
        }
   
    // Driver code
    public static void Main(String[] args) 
    {
        String str1 = "geeksforgeeks";
        String str2 = "forgeeksgeeks";
        int n = str1.Length;
        str2 = str2 + str2;
        KMP(2 * n, n, str2, str1);
    }
}
  
/* This code contributed by PrinciRaj1992 */

chevron_right



Output:

Shift = 8
Prefix = geeksforgeeks


My Personal Notes arrow_drop_up

Discovering ways to develop a plane for soaring career goals

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.