Find the starting indices of the substrings in string (S) which is made by concatenating all words from a list(L) in C++


Suppose we have a string, s, and we have another list with few words, these words are of same length. We have to find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

So if the input is like “wordgoodgoodgoodword” and words are ["word","good"], then the output will be [0,12]. This is because the substring starting at index 0 and 12 are “wordgood” and “goodword”.

To solve this, we will follow these steps −

  • Define a method called ok(), this will take string s, map wordCnt and n −

  • make a copy of s into temp

  • for i in range n to size of s – 1

    • if size of temp is multiple of 0, then

      • if when temp is not present in wordCnt, then return false

      • otherwise

        • if wordCnt[temp] is 1, then delete temp from wordCnt, set temp as an empty string

        • otherwise decrease the value of wordCnt[temp] by 1, set temp as empty string.

    • increase temp by s[i]

  • if temp is not in wordCnt, then return false

  • otherwise

    • if wordCnt[temp] is 1, then delete temp from wordCnt, set temp as an empty string

    • otherwise decrease the value of wordCnt[temp] by 1, set temp as empty string.

  • return true when size of wordCnt is 0

  • From the main method, do this

  • if size of a is 0, or size of b is 0, then return empty array

  • make a map wordCnt, store the frequency of strings present in b into wordCnt

  • make an array called ans

  • window := number of words x number of characters in each word

  • make one copy of string a into temp

  • for i in range window to size of a – 1

    • if temp size is divisible by window and call ok(temp, wordCnt, size of b[0]), then

      • insert i – window into ans

    • insert a[i] into temp

    • if size of temp > window, then delete substring from 0, 1

  • if temp size is divisible by window and call ok(temp, wordCnt, size of b[0]), then

    • insert size of a – window into ans

  • return ans

Example (C++)

Let us see the following implementation to get better understanding −

 Live Demo

#include <bits/stdc++.h>
using namespace std;
void print_vector(vector<auto> v){
   cout << "[";
   for(int i = 0; i<v.size(); i++){
      cout << v[i] << ", ";
   }
   cout << "]"<<endl;
}
class Solution {
public:
   bool ok(string s, unordered_map <string, int> wordCnt, int n){
      string temp = "";
      for(int i = 0; i < n; i++){
         temp += s[i];
      }
      for(int i = n; i < s.size(); i++){
         if(temp.size() % n == 0){
            if(wordCnt.find(temp) == wordCnt.end())return false;
            else{
               if(wordCnt[temp] == 1){
                  wordCnt.erase(temp);
                  temp = "";
               } else {
                  wordCnt[temp]--;
                  temp = "";
               }
            }
         }
         temp += s[i];
      }
   if(wordCnt.find(temp) == wordCnt.end())return false;
   else{
      if(wordCnt[temp] == 1){
         wordCnt.erase(temp);
         temp = "";
      } else {
         wordCnt[temp]--;
         temp = "";
      }
   }
   return wordCnt.size() == 0;
}
vector<int>findSubstring(string a, vector<string> &b) {
   if(a.size() == 0 || b.size() == 0)return {};
      unordered_map <string, int> wordCnt;
   for(int i = 0; i < b.size(); i++)wordCnt[b[i]]++;
      vector <int> ans;
      int window = b.size() * b[0].size();
      string temp ="";
      for(int i = 0; i < window; i++)temp += a[i];
      for(int i = window; i < a.size(); i++){
         if(temp.size() % window == 0 && ok(temp, wordCnt, b[0].size())){
            ans.push_back(i - window);
         }
         temp += a[i];
         if(temp.size() > window)temp.erase(0, 1);
      }
      if(temp .size() % window ==0 && ok(temp, wordCnt, b[0].size()))ans.push_back(a.size() - window);
         return ans;
   }
};
main(){
   vector<string> v = {"word","good"};
   Solution ob;
   print_vector(ob.findSubstring("wordgoodgoodgoodword", v));
}

Input

“wordgoodgoodgoodword”, {"word","good"}

Output

[0, 12, ]

Updated on: 27-Aug-2020

91 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements