📜  字符串及其所有后缀的相似度总和

📅  最后修改于: 2021-04-23 08:18:29             🧑  作者: Mango

给定字符串str ,任务是找到str及其每个后缀的相似度之和。
字符串AB的相似性是最长前缀共同的长度到两个字符串,即“AABC”和“AAB”的相似性是3并且“QWER”和“ABC”的值为0。

例子:

方法:使用Z算法计算Z数组–对于字符串str [0..n-1],Z数组的长度与字符串的长度相同。 Z数组的元素Z [i]存储从str [i]开始的最长子串的长度,该字符串也是str [0..n-1]的前缀。 Z数组的第一个条目是字符串的长度。
现在,对Z数组的所有元素求和,以获得所需的相似度总和。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
#include 
#include 
using namespace std;
  
// Function to calculate the Z-array for the given string
void getZarr(string str, int n, int Z[])
{
    int L, R, k;
  
    // [L, R] make a window which matches with prefix of s
    L = R = 0;
    for (int i = 1; i < n; ++i) {
  
        // if i>R nothing matches so we will calculate.
        // Z[i] using naive way.
        if (i > R) {
            L = R = i;
  
            // R-L = 0 in starting, so it will start
            // checking from 0'th index. For example,
            // for "ababab" and i = 1, the value of R
            // remains 0 and Z[i] becomes 0. For string
            // "aaaaaa" and i = 1, Z[i] and R become 5
            while (R < n && str[R - L] == str[R])
                R++;
            Z[i] = R - L;
            R--;
        }
        else {
  
            // k = i-L so k corresponds to number which
            // matches in [L, R] interval.
            k = i - L;
  
            // if Z[k] is less than remaining interval
            // then Z[i] will be equal to Z[k].
            // For example, str = "ababab", i = 3, R = 5
            // and L = 2
            if (Z[k] < R - i + 1)
                Z[i] = Z[k];
  
            // For example str = "aaaaaa" and i = 2, R is 5,
            // L is 0
            else {
                // else start from R and check manually
                L = i;
                while (R < n && str[R - L] == str[R])
                    R++;
                Z[i] = R - L;
                R--;
            }
        }
    }
}
  
// Function to return the similarity sum
int sumSimilarities(string s, int n)
{
    int Z[n] = { 0 };
  
    // Compute the Z-array for the given string
    getZarr(s, n, Z);
  
    int total = n;
  
    // Summation of the Z-values
    for (int i = 1; i < n; i++)
        total += Z[i];
  
    return total;
}
  
// Driver code
int main()
{
    string s = "ababa";
    int n = s.length();
  
    cout << sumSimilarities(s, n);
    return 0;
}


Java
// Java implementation of the above approach
  
public class GFG{
  
// Function to calculate the Z-array for the given string
static void getZarr(String str, int n, int Z[])
{
    int L, R, k;
  
    // [L, R] make a window which matches with prefix of s
    L = R = 0;
    for (int i = 1; i < n; ++i) {
  
        // if i>R nothing matches so we will calculate.
        // Z[i] using naive way.
        if (i > R) {
            L = R = i;
  
            // R-L = 0 in starting, so it will start
            // checking from 0'th index. For example,
            // for "ababab" and i = 1, the value of R
            // remains 0 and Z[i] becomes 0. For string
            // "aaaaaa" and i = 1, Z[i] and R become 5
            while (R < n && str.charAt(R - L) == str.charAt(R))
                R++;
            Z[i] = R - L;
            R--;
        }
        else {
  
            // k = i-L so k corresponds to number which
            // matches in [L, R] interval.
            k = i - L;
  
            // if Z[k] is less than remaining interval
            // then Z[i] will be equal to Z[k].
            // For example, str = "ababab", i = 3, R = 5
            // and L = 2
            if (Z[k] < R - i + 1)
                Z[i] = Z[k];
  
            // For example str = "aaaaaa" and i = 2, R is 5,
            // L is 0
            else {
                // else start from R and check manually
                L = i;
                while (R < n && str.charAt(R - L) == str.charAt(R))
                    R++;
                Z[i] = R - L;
                R--;
            }
        }
    }
}
  
// Function to return the similarity sum
static int sumSimilarities(String s, int n)
{
    int Z[] = new int[n] ;
  
    // Compute the Z-array for the given string
    getZarr(s, n, Z);
  
    int total = n;
  
    // Summation of the Z-values
    for (int i = 1; i < n; i++)
        total += Z[i];
  
    return total;
}
  
// Driver code
public static void main(String []args)
{
    String s = "ababa";
    int n = s.length();
  
    System.out.println(sumSimilarities(s, n));
}
// This code is contributed by Ryuga
}


Python3
# Python3 implementation of the approach
def getZarr(s, n, Z):
    L, R, k = 0, 0, 0
      
    # [L, R] make a window which matches
    # with prefix of s
    for i in range(n):
        # if i>R nothing matches so we will 
        # calculate Z[i] using naive way.
        if i > R:
            L, R = i, i
              
            '''
            R-L = 0 in starting, so it will start 
            checking from 0'th index. For example, 
            for "ababab" and i = 1, the value of R 
            remains 0 and Z[i] becomes 0. For string 
            "aaaaaa" and i = 1, Z[i] and R become 5
            '''
            while R < n and s[R - L] == s[R]:
                R += 1
            Z[i] = R - L
            R -= 1
        else:
              
            # k = i-L so k corresponds to number 
            # which matches in [L, R] interval.
            k = i - L
              
            # if Z[k] is less than remaining interval 
            # then Z[i] will be equal to Z[k]. 
            # For example, str = "ababab", i = 3, R = 5 
            # and L = 2 
            if Z[k] < R - i + 1:
                Z[i] = Z[k]
            else:
                L = i
                while R < n and s[R - L] == s[R]:
                    R += 1
                Z[i] = R - L
                R -= 1
                  
def sumSimilarities(s, n):
    Z = [0 for i in range(n)]
      
    # Compute the Z-array for the 
    # given string
    getZarr(s, n, Z)
      
    total = n
      
    # summation of the Z-values
    for i in range(n):
        total += Z[i]
    return total
      
# Driver Code
s = "ababa"
  
n = len(s)
  
print(sumSimilarities(s, n))
  
# This code is contributed 
# by Mohit kumar 29


C#
//C# implementation of the above approach
using System;
  
public class GFG{
    // Function to calculate the Z-array for the given string
static void getZarr(string str, int n, int []Z)
{
    int L, R, k;
  
    // [L, R] make a window which matches with prefix of s
    L = R = 0;
    for (int i = 1; i < n; ++i) {
  
        // if i>R nothing matches so we will calculate.
        // Z[i] using naive way.
        if (i > R) {
            L = R = i;
  
            // R-L = 0 in starting, so it will start
            // checking from 0'th index. For example,
            // for "ababab" and i = 1, the value of R
            // remains 0 and Z[i] becomes 0. For string
            // "aaaaaa" and i = 1, Z[i] and R become 5
            while (R < n && str[R - L] == str[R])
                R++;
            Z[i] = R - L;
            R--;
        }
        else {
  
            // k = i-L so k corresponds to number which
            // matches in [L, R] interval.
            k = i - L;
  
            // if Z[k] is less than remaining interval
            // then Z[i] will be equal to Z[k].
            // For example, str = "ababab", i = 3, R = 5
            // and L = 2
            if (Z[k] < R - i + 1)
                Z[i] = Z[k];
  
            // For example str = "aaaaaa" and i = 2, R is 5,
            // L is 0
            else {
                // else start from R and check manually
                L = i;
                while (R < n && str[R - L] == str[R])
                    R++;
                Z[i] = R - L;
                R--;
            }
        }
    }
}
  
// Function to return the similarity sum
static int sumSimilarities(string s, int n)
{
    int []Z = new int[n] ;
  
    // Compute the Z-array for the given string
    getZarr(s, n, Z);
  
    int total = n;
  
    // Summation of the Z-values
    for (int i = 1; i < n; i++)
        total += Z[i];
  
    return total;
}
  
// Driver code
    static public void Main (){
          
    string s = "ababa";
    int n = s.Length;
  
    Console.WriteLine(sumSimilarities(s, n));
}
// This code is contributed by ajit.
}


输出:
9