Search code examples
c++stringsubstringsubsequence

How to get a substring by deleting minimum number of characters?


In this question, we take 2 strings as input say s1 and s2.

Now, first we need to check if s2 is a subsequence of s1. If not, print no.

But if it is, we need to print the minimum number of characters to be deleted from s1 to get s2.

Eg- thistext text

Here, text can be directly found without deleting any characters so the answer is 0.

Eg- cutefriendship crisp

In this case, the answer is 9.

What I've done so far,

#include <bits/stdc++.h>
using namespace std;

int checkIfSub(string s1, string s2, int m, int n)
{
    int j = 0;
    for(int i = 0; i < m && j < n; i++)
        if(s1[i] == s2[j])
            j++;
    if(j == n)
        return 0;
    else 
        return 1;
}
int check(string s1, string s2)
{
    int count = 0; string s3;
    if(checkIfSub(s1, s2, s1.length(), s2.length()) == 1 || s2.length() > s1.length())
    {
        cout << "NO\n"; return 0;
    }
    int j = 0;
    for(int i = 0; i < s1.length(); i++)
    {
        if(s1[i] == s2[j])
        {
            s3[j] = s1[j];
            j++; continue;
        }
        count++;
    }
    cout << "YES " << count << "\n";
    return 0;
}

int main() {

    string s1, s2;
    cin >> s1 >> s2;
    check(s1, s2);

    return 0;
}

My code works well for the second example, but fails the first case.

(This was a question asked in some interview I read online.)


Solution

  • Try something like this:

    #include <iostream>
    #include <string>
    using namespace std;
    
    bool check(const string &s1, const string &s2, int &minToDelete)
    {
        minToDelete = 0;
        bool anySubSeqFound = false;
    
        if (s2.empty())
            return false;
    
        string::size_type first = 0;
        while ((first = s1.find(s2[0], first)) != string::npos)
        {
            int numDeleted = 0;
            bool isSubSeq = true;
    
            string::size_type next = first + 1;
            for(string::size_type j = 1; j < s2.size(); ++j)
            {
                string::size_type found = s1.find(s2[j], next);
                if (found == string::npos)
                {
                    isSubSeq = false;
                    break;
                }
                numDeleted += (found - next);
                next = found + 1;
            }
    
            if (isSubSeq)
            {
                if (anySubSeqFound)
                {
                    if (numDeleted < minToDelete)
                        minToDelete = numDeleted;
                }
                else
                {           
                    anySubSeqFound = true;
                    minToDelete = numDeleted;
                }
            }
    
            ++first;
        }
    
        return anySubSeqFound;
    }
    
    int main()
    {
        int minToDelete;
    
        if (check("thistext", "text", minToDelete))
            cout << "yes, delete " << minToDelete << endl;
        else
            cout << "no" << endl;
    
        if (check("cutefriendship", "crisp", minToDelete))
            cout << "yes, delete " << minToDelete << endl;
        else
            cout << "no" << endl;
    }
    

    Live Demo