-1

I was trying to solve Reduce String on codechef which says Give a string s of length l, and a set S of n sample string(s). We do reduce the string s using the set S by this way: Wherever Si appears as a consecutive substring of the string s, you can delete (or not) it. After each deletion, you will get a new string s by joining the part to the left and to the right of the deleted substring.

I wrote a recursive function as follows:- Basically what i am doing in my code is either don't delete the character or delete it if it is part of any substring but it is giving wrong answer.

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

int dp[mx];
unordered_map<string,int> sol;

void init(int n)
{
    for(int i=0;i<n;i++)
    {
        dp[i]=-1;
    }
}

int solve(string str,int low,int high,vector<string> smp)
{
     if(low>high)
     {
        return 0;
     }
     if(dp[low]!=-1)
     {
        return dp[low];
     }
     int ans=1+solve(str,low+1,high,smp);
     for(int i=low;i<high;i++)
     {
        string tem=str.substr(low,i-low+1);
        for(int j=0;j<smp.size();j++)
        {
            cout<<"low i high str"<<low<<" "<<i<<" "<<high<<" "<<smp[j]<<" "<<tem<<endl;
            if(tem.compare(smp[j])==0)
            {
                ans=min(ans,solve(str,i+1,high,smp));
            }
        }
     }
     return dp[low]=ans;
}

signed main()
{
    sol.clear();
    string str;
    vector<string> smp;
    int n;
    cin>>str;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        string tem;
        cin>>tem;
        smp.push_back(tem);
    }
    int len=str.length();
    init(len+1);
    cout<<solve(str,0,len-1,smp)<<endl;
    return 0;
}

PS: link to the question

  • 2
    You should *never* `#include `. It is not proper C++. It ruins portability and fosters terrible habits. See [Why should I not `#include `](https://stackoverflow.com/q/31816095). Also, please try to avoid `using namespace std;` because it is [considered bad practice?](https://stackoverflow.com/q/1452721) Have you tried running your code through a debugger? You should identify the problematic code and post the minimal code required to reproduce the problem. See [mre] for more information. – L. F. Jan 14 '20 at 13:57
  • 1
    Why do you think dynamic programming on the length of the string is valid? If your remove-strings are 'a' and 'b', and the string is 'aaaabb', there are a whole pile of 4 long possible strings, and those 4 long possible strings all differ in how they can become shorter. – Yakk - Adam Nevraumont Jan 14 '20 at 13:58
  • 1
    Also, if you're going to code up a dynamic programming solution, you had better be sure your plan, on paper, works before writing any code. Otherwise you're just going to go down a rabbit hole with an invalid solution. – PaulMcKenzie Jan 14 '20 at 14:01
  • 2
    It's the first time I ever see `signed main()` :) – YSC Jan 14 '20 at 14:17
  • @PaulMcKenzie yes you were right the code was wrong :/.But i have added answer why my code in the question was wrong and what will be right code.Thanks for the help. – Anurag Maurya Jan 21 '20 at 04:09

1 Answers1

-1

This question is toughest(seen so far) and most beautiful(again seen so far) question based on DP ON INTERVALS.
The initial code would definitely not work since it only considers single pass on the string and would not consider remaining string after deleting the patterns again and again.
There are 3 cases:-
Case 1 Either character is not deleted.
Case 2It is deleted as a part of contiguous substring.
Case 3It is deleted as a part of subsequence that matches any word given in the set of patterns and everything that is not part of that subsequence is deleted first as a substring(which again belongs to set of words).
The third part is the most tricky and requires enough thinking and is even tougher to implement too.
So for every substring we need to check whether this substring can be completely destroyed or not. The function compute_full_recur() is the function that ensures that whether substring can be deleted either in Case 2 or Case 3.
The function compute_full takes care of Case 1.
And finally this code will not run on codechef link since all the function are recursive with memoization but to verify the code is working i Have run it on Problem Reducto of Hackerrank which is exact similar with lower constraints.Download test cases and then run on test cases on your PC for verifying.

#include <iostream>
#include <vector>
#include <string>
using namespace std;
#define mx 252
#define nx 40
bool full[mx][mx],vis[mx][mx],full_recur[mx][mx][nx][nx];
int ans[mx];

void init()
{
    for(int i=0;i<mx;i++)
    {
        for(int j=0;j<mx;j++)
        {
            full[i][j]=false,vis[i][j]=false;
        }
    }

    for(int i=0;i<mx;i++)
    {
        ans[i]=-1;
    }

    for(int i=0;i<mx;i++)
    {
        for(int j=0;j<mx;j++)
        {
            for(int k=0;k<nx;k++)
            {
                for(int l=0;l<nx;l++)
                {
                    full_recur[i][j][k][l]=false;
                }
            }
        }
    }

}

bool compute_full_recur(string str,int low,int high,vector<string> pat,int idx,int len)
{
    if(low>high&&len==pat[idx].length())
    {
        return true;
    }
    if(low>high&&len<pat[idx].length())
    {
        full_recur[low][high][idx][len]=false;
        return false;
    }
    if(str[low]==pat[idx][len]&&compute_full_recur(str,low+1,high,pat,idx,len+1))
    {
        return full_recur[low][high][idx][len]=true;
    }
    for(int i=low+1;i<=high;i++)
    {
        if(str[low]==pat[idx][len]&&full[low+1][i]&&compute_full_recur(str,i+1,high,pat,idx,len+1))
        {
            return full_recur[low][high][idx][len]=true;
        }
    }
    full_recur[low][high][idx][len]=false;
    return false;
}

void compute_full(string str,int low,int high,vector<string> pats)
{
    if(low>high)
    {
        return;
    }
    if(vis[low][high])
    {
        return;
    }
    vis[low][high]=true;
    compute_full(str,low+1,high,pats);
    compute_full(str,low,high-1,pats);
    for(int i=0;i<pats.size();i++)
    {
        if(!full[low][high])
        full[low][high]=compute_full_recur(str,low,high,pats,i,0);
    }
}

int compute_ans(string str,int low,int high)
{
    if(low>high)
    {
        return 0;
    }
    if(ans[low]!=-1)
    {
        return ans[low];
    }
    int sol=1+compute_ans(str,low+1,high);
    for(int i=low+1;i<=high;i++)
    {
        if(full[low][i]==true)
        {
            sol=min(sol,compute_ans(str,i+1,high));
        }
    }
    return ans[low]=sol;
}

signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        string str;
        int n;
        vector<string> pats;
        cin>>n>>str;
        for(int i=0;i<n;i++)
        {
            string tem;
            cin>>tem;
            pats.push_back(tem);
        }
        init();
        compute_full(str,0,str.length()-1,pats);
        cout<<compute_ans(str,0,str.length()-1)<<endl;
    }
    return 0;
}
  • answer got downvoted although it was verified but that's fine .The only problem is why question got downvoted.it could have helped somebody.:) – Anurag Maurya Aug 27 '20 at 16:21