Рубрики

Самый длинный общий префикс с использованием бинарного поиска

Учитывая набор строк, найдите самый длинный общий префикс.

Input  : {“geeksforgeeks”, “geeks”, “geek”, “geezer”}
Output : "gee"

Input  : {"apple", "ape", "april"}
Output : "ap"


Input  : {"abcd"}
Output : "abcd"

Предыдущие подходы — сопоставление по словам , сопоставление по символам , разделяй и властвуй

В этой статье обсуждается подход с использованием бинарного поиска .
шаги:

  1. Найдите строку, имеющую минимальную длину. Пусть эта длина будет L.
  2. Выполните бинарный поиск по любой строке (из входного массива строк). Давайте возьмем первую строку и сделаем двоичный поиск по символам из индекса — от 0 до L-1 .
  3. Вначале возьмите low = 0 и high = L-1 и разделите строку на две половины — левую (от низкой к середине) и правую (от середины + 1 до высокой) .
  4. Проверьте, присутствуют ли все символы в левой половине в соответствующих индексах (от низкого до среднего) всех строк или нет. Если он присутствует, мы добавляем эту половину к нашей строке префикса и смотрим в правую половину в надежде найти более длинный префикс (гарантируется, что здесь есть общая строка префикса).
  5. В противном случае, если все символы в левой половине не присутствуют в соответствующих индексах (от низкого до среднего) во всех строках, то нам не нужно смотреть на правую половину, поскольку в самой левой половине есть некоторые символы, которые не является частью самой длинной строки префикса. Таким образом, мы действительно смотрим на левую половину в надежде найти общую строку префикса. (Возможно, мы не найдем какой-либо общей строки префикса)

Иллюстрация алгоритма, рассматривающая строки как — «geeksforgeeks», «geeks», «geek», «geezer»

Ниже приведена реализация вышеуказанного подхода.

C ++

// Программа на C ++, чтобы найти самый длинный общий префикс
#include<bits/stdc++.h>

using namespace std;

  
// Функция для поиска строки, имеющей минимум
// длина и возвращает эту длину

int findMinLength(string arr[], int n)

{

    int min = INT_MAX;

  

    for (int i=0; i<=n-1; i++)

        if (arr[i].length() < min)

            min = arr[i].length();

    return(min);

}

  

bool allContainsPrefix(string arr[], int n, string str,

                       int start, int end)

{

    for (int i=0; i<=n-1; i++)

        for (int j=start; j<=end; j++)

            if (arr[i][j] != str[j])

                return (false);

    return (true);

}

  
// Функция, которая возвращает самый длинный общий префикс
// из массива строк

string commonPrefix(string arr[], int n)

{

    int index = findMinLength(arr, n);

    string prefix; // Наша результирующая строка

  

    // Мы сделаем бинарный поиск на месте

    // первая строка массива в диапазоне от 0 до

    // показатель

    int low = 0, high = index;

  

    while (low <= high)

    {

        // То же, что (low + high) / 2, но избегает переполнения

        // для больших низких и высоких

        int mid = low + (high - low) / 2;

  

        if (allContainsPrefix (arr, n, arr[0], low, mid))

        {

            // Если все строки во входном массиве содержат

            // этот префикс затем добавляем эту подстроку в

            // наш ответ

            prefix = prefix + arr[0].substr(low, mid-low+1);

  

            // А потом перейти на правильную часть

            low = mid + 1;

        }

  

        else // Перейти к левой части

            high = mid - 1;

    }

  

    return (prefix);

}

  
// Программа драйвера для проверки вышеуказанной функции

int main()

{

    string arr[] = {"geeksforgeeks", "geeks",

                    "geek", "geezer"};

    int n = sizeof (arr) / sizeof (arr[0]);

  

    string ans = commonPrefix(arr, n);

  

    if (ans.length())

        cout << "The longest common prefix is "

             << ans;

    else

        cout << "There is no common prefix";

    return (0);

}

Джава

// Программа на Java, чтобы найти самый длинный общий префикс

  

class GFG {

  

    // Функция для поиска строки, имеющей

    // минимальная длина и возвращает эту длину

    static int findMinLength(String arr[], int n)

    {

        int min = Integer.MAX_VALUE;

        for (int i = 0; i <= (n - 1); i++) 

        {

            if (arr[i].length() < min) {

                min = arr[i].length();

            }

        }

        return min;

    }

  

    static boolean allContainsPrefix(String arr[], int n, 

                         String str, int start, int end)

    {

        for (int i = 0; i <= (n - 1); i++)

        {

            String arr_i = arr[i];

              

            for (int j = start; j <= end; j++)

                if (arr_i.charAt(j) != str.charAt(j))

                    return false;

        }

        return true;

    }

  

    // Функция, которая возвращает самый длинный общий префикс

    // из массива строк

    static String commonPrefix(String arr[], int n)

    {

        int index = findMinLength(arr, n);

        String prefix = ""; // Наша результирующая строка

  

        // Мы сделаем бинарный поиск на месте

        // первая строка массива в диапазоне от 0 до

        // показатель

        int low = 0, high = index-1;

        while (low <= high) {

              

            // То же, что (low + high) / 2, но избегает

            // переполнение для большого минимума и максимума

            int mid = low + (high - low) / 2;

  

            if (allContainsPrefix(arr, n, arr[0], low,

                                                  mid))

            {

                // Если все строки во входном массиве

                // содержит этот префикс и добавляем

                // подстрока к нашему ответу

                prefix = prefix + arr[0].substring(low,

                                          mid + 1);

  

                // А потом перейти на правильную часть

                low = mid + 1;

            

            else // Перейти к левой части

            {

                high = mid - 1;

            }

        }

  

        return prefix;

    }

  

    // Программа драйвера для проверки вышеуказанной функции

    public static void main(String args[])

    {

        String arr[] = {"geeksforgeeks", "geeks",

                               "geek", "geezer"};

        int n = arr.length;

  

        String ans = commonPrefix(arr, n);

          

        if (ans.length() > 0)

            System.out.println("The longest common"

                            + " prefix is " + ans);

        else 

            System.out.println("There is no common" 

                                      + " prefix");

    }

}

  
// Этот код предоставлен Индраджит Синха.

C #

// C # Программа для поиска самого длинного общего префикса с использованием System;

using System;                

public class GFG {

   

    // Функция для поиска строки, имеющей

    // минимальная длина и возвращает эту длину

    static int findMinLength(string []arr, int n)

    {

        int min = int.MaxValue;

        for (int i = 0; i <= (n - 1); i++) 

        {

            if (arr[i].Length < min) {

                min = arr[i].Length;

            }

        }

        return min;

    }

   

    static bool allContainsPrefix(string []arr, int n, 

                         string str, int start, int end)

    {

        for (int i = 0; i <= (n - 1); i++)

        {

            string arr_i = arr[i];

               

            for (int j = start; j <= end; j++)

                if (arr_i[j] != str[j])

                    return false;

        }

        return true;

    }

   

    // Функция, которая возвращает самый длинный общий префикс

    // из массива строк

    static string commonPrefix(string []arr, int n)

    {

        int index = findMinLength(arr, n);

        string prefix = ""; // Наша результирующая строка

   

        // Мы сделаем бинарный поиск на месте

        // первая строка массива в диапазоне от 0 до

        // показатель

        int low = 0, high = index;

        while (low <= high) {

               

            // То же, что (low + high) / 2, но избегает

            // переполнение для большого минимума и максимума

            int mid = low + (high - low) / 2;

   

            if (allContainsPrefix(arr, n, arr[0], low,

                                                  mid))

            {

                // Если все строки во входном массиве

                // содержит этот префикс и добавляем

                // подстрока к нашему ответу

                prefix = prefix + arr[0].Substring(low,

                                          mid + 1);

   

                // А потом перейти на правильную часть

                low = mid + 1;

            

            else // Перейти к левой части

            {

                high = mid - 1;

            }

        }

   

        return prefix;

    }

   

    // Программа драйвера для проверки вышеуказанной функции

    public static void Main()

    {

        string []arr = {"geeksforgeeks", "geeks",

                               "geek", "geezer"};

        int n = arr.Length;

  

        string ans = commonPrefix(arr, n);

           

        if (ans.Length > 0)

            Console.WriteLine("The longest common"

                            + " prefix is - " + ans);

        else

            Console.WriteLine("There is no common"

                                      + " prefix");

    }

}

   
// Этот код предоставлен PrinciRaj1992

Выход :

The longest common prefix is - gee

Сложность времени:
Отношение повторения

T(M) = T(M/2) + O(MN) 

где

N = Number of strings
M = Length of the largest string

Таким образом, мы можем сказать, что сложность по времени O (NM log M)

Вспомогательное пространство: для хранения самой длинной строки префикса мы выделяем пространство, которое равно O (N), где N = длина самой большой строки среди всех строк.

Эта статья предоставлена Rachit Belwariar . Если вы как GeeksforGeeks и хотели бы внести свой вклад, вы также можете написать статью с помощью contribute.geeksforgeeks.org или по почте статьи contribute@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой теме

Рекомендуемые посты:

Самый длинный общий префикс с использованием бинарного поиска

0.00 (0%) 0 votes