2

Can someone explain to me how to solve the substring problem iteratively?

The problem: given two strings S=S1S2S3Sn and T=T1T2T3Tm, with m is less than or equal to n, determine if T is a substring of S.

2
  • Almost the same question and the answers at stackoverflow.com/questions/1261041/substring-algorithm Commented Sep 2, 2009 at 20:09
  • 1
    am I the only one who objects at solving other people's homework? :( Commented Sep 3, 2009 at 7:21

11 Answers 11

4

Here's a list of string searching algorithms

Depending on your needs, a different algorithm may be a better fit, but Boyer-Moore is a popular choice.

Sign up to request clarification or add additional context in comments.

Comments

3

A naive algorithm would be to test at each position 0 < in-m of S if Si+1Si+2Si+m=T1T2Tm. For n=7 and m=5:

i=0:  S1S2S3S4S5S6S7
      | | | | |
      T1T2T3T4T5

i=1:  S1S2S3S4S5S6S7
        | | | | |
        T1T2T3T4T5

i=2:  S1S2S3S4S5S6S7
          | | | | |
          T1T2T3T4T5

The algorithm in pseudo-code:

// we just need to test if n ≤ m 
IF n > m:
    // for each offset on that T can start to be substring of S
    FOR i FROM 0 TO n-m:
        // compare every character of T with the corresponding character in S plus the offset
        FOR j FROM 1 TO m:
            // if characters are equal
            IF S[i+j] == T[j]:
                // if we’re at the end of T, T is a substring of S
                IF j == m:
                    RETURN true;
                ENDIF;
            ELSE:
                BREAK;
            ENDIF;
        ENDFOR;
    ENDFOR;
ENDIF;
RETURN false;

1 Comment

This also fails for the case of m == 0 (an empty string is a substring of any other string).
3

Not sure what language you're working in, but here's an example in C#. It's a roughly n2 algorithm, but it will get the job done.

bool IsSubstring (string s, string t)
{
   for (int i = 0; i <= (s.Length - t.Length); i++)
   {
      bool found = true;

      for (int j = 0; found && j < t.Length; j++)
      {
         if (s[i + j] != t[j])
             found = false;
      }

      if (found)
         return true;
   }

   return false;
}

3 Comments

break; after found=false; would reduce complexity
Alice - not necessary; its part of the loop condition of the for loop.
The fact that this checks for inequality instead of equality makes it confusing imo. Is there any benefit to this approach?
2
if (T == string.Empty) return true;
for (int i = 0; i <= S.Length - T.Length; i++) {
    for (int j = 0; j < T.Length; j++) {
        if (S[i + j] == T[j]) {
            if (j == (T.Length - 1)) return true;
        }
        else break;
    }
}
return false;

4 Comments

continue looks to be redundant here
Ok fixed it. but a good compiler doesn't make a difference there anyway.
You have a fencepost error in your first for loop, the condition should be i <= S.Length - T.Length.
Oh and your logic also fails for the case where T is an empty string (an empty string is a substring of any other string).
1

It would go something like this:

m==0? return true
cs=0
ct=0
loop
    cs>n-m? break
    char at cs+ct in S==char at ct in T?
    yes:
        ct=ct+1
        ct==m? return true
    no:
        ct=0
        cs=cs+1

end loop
return false

1 Comment

That should be ct == m not n. It also falls to the same problem that several other answers have - it returns false if T is an empty string, which is not correct.
1

This may be redundant with the above list of substring algorithms, but I was always amused by KMP (http://en.wikipedia.org/wiki/Knuth–Morris–Pratt_algorithm)

Comments

1
// runs in best case O(n) where no match, worst case O(n2) where strings match

var s = "hippopotumus"
var t = "tum"

for(var i=0;i<s.length;i++)
    if(s[i]==t[0])
        for(var ii=i,iii=0; iii<t.length && i<s.length; ii++, iii++){
            if(s[ii]!=t[iii]) break
            else if (iii==t.length-1) console.log("yay found it at index: "+i)
        }

Comments

0

Here is my PHP variation that includes a check to make sure the Needle does not exceed the Haystacks length during the search.

<?php

function substring($haystack,$needle) {
        if("" == $needle) { return true; }
        echo "Haystack:\n$haystack\n";
    echo "Needle:\n$needle\n";

        for($i=0,$len=strlen($haystack);$i<$len;$i++){
                if($needle[0] == $haystack[$i]) {
                        $found = true;
                        for($j=0,$slen=strlen($needle);$j<$slen;$j++) {
                                if($j >= $len) { return false; }
                                if($needle[$j] != $haystack[$i+$j]) {
                                        $found = false;
                                        continue;
                                }
                        }
                        if($found) {
                                echo " . . . . . . SUCCESS!!!! startPos: $i\n";
                                return true;
                        }
                }
        }
        echo " . . . . . . FAILURE!\n" ;
        return false;
}

assert(substring("haystack","hay"));
assert(!substring("ack","hoy"));
assert(substring("hayhayhay","hayhay"));
assert(substring("mucho22","22"));
assert(!substring("str","string"));
?>

Left in some echo's. Remove if they offend you!

Comments

0

Is a O(n*m) algorithm, where n and m are the size of each string. In C# it would be something similar to:

   public static bool IsSubtring(char[] strBigger, char[] strSmall)
        {
            int startBigger = 0;
            while (startBigger <= strBigger.Length - strSmall.Length)
            {
                int i = startBigger, j = 0;

                while (j < strSmall.Length && strSmall[j] == strBigger[i])
                {
                    i++;
                    j++;
                }

                if (j == strSmall.Length)
                    return true;
                startBigger++;
            }

            return false;
        }

Comments

0

I know I'm late to the game but here is my version of it (in C#):

    bool isSubString(string subString, string supraString)
    {
        for (int x = 0; x <= supraString.Length; x++)
        {
            int counter = 0;
            if (subString[0] == supraString[x]) //find initial match
            {
                for (int y = 0; y <= subString.Length; y++)
                {
                    if (subString[y] == supraString[y+x])
                    {
                        counter++;
                        if (counter == subString.Length)
                        {
                            return true;
                        }
                    } 
                }
            }
        }
        return false;
    }

Comments

0

Though its pretty old post, I am trying to answer it. Kindly correct me if anything is wrong,

package com.amaze.substring;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class CheckSubstring {

/**
 * @param args
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    System.out.println("Please enter the main string");
    String mainStr = br.readLine();

    System.out.println("Enter the substring that has to be searched");
    String subStr = br.readLine();

    char[] mainArr = new char[mainStr.length()];
    mainArr = mainStr.toCharArray();
    char[] subArr = new char[subStr.length()];
    subArr = subStr.toCharArray();
    boolean tracing = false;
    //System.out.println("Length of substring is "+subArr.length);
    int j = 0;

    for(int i=0; i<mainStr.length();i++){

        if(!tracing){
            if(mainArr[i] == subArr[j]){
                tracing = true;
                j++;
            }
        } else {
            if (mainArr[i] == subArr[j]){
                //System.out.println(mainArr[i]);
                //System.out.println(subArr[j]);
                j++;
                System.out.println("Value of j is "+j);
                if((j == subArr.length)){
                    System.out.println("SubString found");
                    return;
                }
            } else {
                j=0;
                tracing = false;
            }
        }
    }

    System.out.println("Substring not found");

}

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.