Can the string be segmented in JavaScript


The problem statement says to check if the string given by the user as an input can be segmented or not .

What is a Segmented String ?

Segmentation in string refers to breaking down words in the whole string text as an input . The words are broken down into the words of the dictionary. The problem statement is more established and dug deeper down into given some wholesome dictionaries of words and string text and we have to check if the segmented or broken down of string is compatible and equal to words of the dictionary mentioned .

The problem statement can be visualized with the output given below :

Given dictionary of words :  “apple , peer , pie , please , have “

Input String : “haveapplepie”

Output :  true 

If the input string can be segmented and broken down in respect to the dictionary words mentioned by the user , the resultant output returns true else it will return false.

Algorithm

The algorithm here mentioned is a brute force approach of using loop and include method of javascript to find and check if the input string can be segmented or not .

Step 1 : Declare a function with name checkSegmentation that takes in string array as an input and dictionary array as some set of words using which one can find out if the particular string can be segmented or not .

Step 2 : Starting with the for loop one can traverse through each and every character of the string till stringArray.length .

Step 3 : When the value of i = 0 , we store the value as the first word using substr method in a variable firstSubString.

Step 4 : Then we try to find if the dictionary of words includes the value stored in firstSubString using the include javascript method.

Step 5 : If the dictionary includes the first substring , we store the second Substring that starts after the firstWord in secondSubString variable

Step 6 : If the length of the secondSubString variable is 0 , it returns only the firstSubString segmented string that is found already in the dictionary , and returns true as the resultant output.

Step 7 : If the secondSubString is already present in the dictionary of words using the include method , then also the resultant output returns true stating string can be segmented .

Step 8 : If any of the above mentioned steps in 6 or 7 points does not happen , the main function checkSegmentation becomes a recursive function to perform all the operations and algorithms steps mentioned above for secondSubString in respect to the dictionary of words.

Example

function checkSegmentation(stringArray, dictionaryArray) {

   for (let i = 1; i < stringArray.length + 1; i++) 
     {

     let firstSubString = stringArray.substr(0, i);

      if (dictionaryArray.includes(firstSubString)) {

        let secondSubString = stringArray.substr(i);

     if (secondSubString.length === 0) {

         return true;
      }

     if (dictionaryArray.includes(secondSubString)) {

         return true;
      }
     
     if (checkSegmentation(secondSubString, dictionaryArray)) {
       
        return true;

      }

     }

   }

return false;

};

const dictionaryArray =  "apple , peer , pie , please , have ";

const stringArray =  "haveapple";

console.log(checkSegmentation(stringArray,dictionaryArray));

Output

true

The following code is the simplest way one can think of while looking at the problem statement , later we can optimize it to the better quality of space and time making it more efficient and high quality.

In the above code we have declared a function checkSegmentation that is defined with string array and dictionary values to check segmentation of string.

Here we are iterating through every element of the string such that constructing sub words every single time with each iteration in hope of finding that subword in the dictionary using the javascript include method.

Time and Space Complexity

As the algorithm is recursive algorithm and everytime goes for a recursive function when it cannot find second substring included dictionary till the length of the string array , it results an exponential worst case time complexity of O(2^n) because the recursive function leads to sub recursive branches forming a tree like structure with height of 2^n thus complexity becomes assured by that.

We can improve the time complexity toO(n^2) using Memoization where memoization will take some memory to store the steps that are already performed for certain letters , instead of repeating them again.

With above algorithm we may be computing the same substring or character multiple times differently every time we iterate over forwarding and moving towards length of string array even if the substring that is completed may be two or more times does not exist in dictionary , this increases the recursive sub calls and memoization can reduce that part for the algorithm.

Memoization is something where we will remember the substrings that have already been solved.

Algorithm - using Memoization

Step 1 : Declare a main function with name segmentString that takes string array and dictionary of words as an input.

Step 2 : Return a helper and recursive function from it that takes in string array , dictionary of words , start of the string , empty array for memoization

Step 3 : Inside the helper function with name recursiveWordFind we use the base cases of if string array equals to length return true and if memo array start position is not equal to undefined , return back the memory of the starting index.

Step 4 : Traverse the string array with start and end position flags such that first word or first substring is the array with start position and second substring starts with indexing of start +1 for end flag.

Step 5 : Extract out the substring in between the start and the end position and store it in the inputSubString variable.

Step 6 : Once you find a particular substring in between start and end position in the dictionary and repeat again the recursive function for leftover characters present in the main string array , return back the memory references of all the string characters so that the same recursive function is not repeated for the already traversed substring hence saving the power of function .

Main Code - using Memoization

Example

function segmentString(  stringArray , dictionaryArray )
{
   return recursiveWordFind( stringArray , dictionaryArray , 0  , []);
}



function recursiveWordFind( stringArray  ,dictionaryArray , start , memo )
{ 
   if(start===stringArray.length) return true ;

   if(memo[start]!==undefined) return memo[start];

   for(let end = start +1 ; end <= stringArray.length ; end++)
   {

     let inputSubString = stringArray.substring(start,end);

     if(dictionaryArray.includes(inputSubString) && recursiveWordFind(stringArray , dictionaryArray , end , memo))

     {
       
      return memo[start]=true;

     }

   }

   return memo[start]=false;
}

const dictionaryArray =  ["apple", "pen"];

const stringArray =  "applepenapple";

console.log(segmentString(stringArray,dictionaryArray));

Output

true 

Time and Space Complexity

Memoization uses the memory reference or memory container that just saves the cycling of loop and recursive functions such that due to this the time complexity is reduced from exponential worst time to quadratic time complexity ie. O(n^2).

Conclusion

This is how we can solve the above problem statement thinking logically and in the context of coding , where this kind of problem statement can grow efficiently in respect to time , optimization and best efficiency .

Updated on: 22-Aug-2023

191 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements