Distinct Echo Substrings in C++


Suppose we have a string S; we have to find the number of distinct non-empty substrings of S that can be written as the concatenation of some string with itself.

So, if the input is like "elloelloello", then the output will be 5, as there are some substrings like "ello", "lloe", "loel", "oell".

To solve this, we will follow these steps −

  • prime := 31

  • m := 1^9 + 7

  • Define a function fastPow(), this will take base, power,

  • res := 1

  • while power > 0, do −

    • if power & 1 is non-zero, then −

      • res := res * base

      • res := res mod m

    • base := base * base

    • base := base mod m

    • power = power / 2

  • return res

  • Define a function createHashValue(), this will take s, n,

  • result := 0

  • for initialize i := 0, when i < n, update (increase i by 1), do −

    • result := result + (s[i] * fastPow(prime, i))

    • result := result mod m

  • return result

  • Define a function recalculateHash(), this will take old, newC, oldHash, patLength,

  • newHash := oldHash - old

  • newHash := newHash * fastPow(prime, m - 2)

  • newHash := newHash + (newC * fastPow(prime, patLength - 1))

  • newHash := newHash mod m

  • return newHash

  • From the main method do the following −

  • n := size of text

  • Define one set ans

  • for initialize i := 2, when i <= n, update i := i + 2, do −

    • temp := empty string

    • for initialize j := 0, when j < i / 2, update (increase j by 1), do −

      • temp := temp + text[j]

    • hash1 := createHashValue(temp, i / 2)

    • temp := empty string)

    • for initialize j := i / 2, when j < i, update (increase j by 1), do −

      • temp := temp + text[j]

    • hash2 := createHashValue(temp, i / 2)

    • for initialize s1 := 0, e1 := i / 2, s2 := i / 2, e2 := i, when e2 < n, update (increase s1, s2, e1, e2 by 1), do −

      • if hash1 is same as hash2, then

        • insert hash1 into ans

      • hash1 := recalculateHash(text[s1], text[e1], hash1, i / 2)

      • hash2 := recalculateHash(text[s2], text[e2], hash2, i / 2)

    • if hash1 is same as hash2, then

      • insert hash1 into ans

  • return size of ans

Let us see the following implementation to get better understanding −

Example

 Live Demo

#include <bits/stdc++.h>
using namespace std;
typedef long long int lli;
const lli prime = 31;
const lli m = 1e9 + 7;
class Solution {
   public:
   lli fastPow(lli base, lli power){
      lli res = 1;
      while (power > 0) {
         if (power & 1) {
            res = res * base;
            res %= m;
         }
         base *= base;
         base %= m;
         power >>= 1;
      }
      return res;
   }
   lli createHashValue(string s, lli n){
      lli result = 0;
      for (lli i = 0; i < n; i++) {
         result += (lli)(s[i] * fastPow(prime, i));
         result %= m;
      }
      return result;
   }
   lli recalculateHash(char old, char newC, lli oldHash, lli
   patLength){
      lli newHash;
      newHash = oldHash - (lli)old;
      newHash *= fastPow(prime, m - 2);
      newHash += ((lli)newC * fastPow(prime, patLength - 1));
      newHash %= m;
      return newHash;
   }
   int distinctEchoSubstrings(string text){
      int n = text.size();
      set<int> ans;
      for (int i = 2; i <= n; i += 2) {
         string temp = "";
         for (int j = 0; j < i / 2; j++) {
            temp += text[j];
         }
         int hash1 = createHashValue(temp, i / 2);
         temp = "";
         for (int j = i / 2; j < i; j++) {
            temp += text[j];
         }
         int hash2 = createHashValue(temp, i / 2);
         for (int s1 = 0, e1 = i / 2, s2 = i / 2, e2 = i; e2 < n;
         s1++, s2++, e1++, e2++) {
            if (hash1 == hash2) {
               ans.insert(hash1);
            }
            hash1 = recalculateHash(text[s1], text[e1], hash1,
            i / 2);
            hash2 = recalculateHash(text[s2], text[e2], hash2,
            i / 2);
         }
         if (hash1 == hash2) {
            ans.insert(hash1);
         }
      }
      return ans.size();
   }
};
main(){
   Solution ob;
   cout << (ob.distinctEchoSubstrings("elloelloello"));
}

Input

"elloelloello"

Output

5

Updated on: 08-Jun-2020

83 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements