I understood that we can use dynamic programming here but my first intuition was to use stack since s3 is made up of substrings of s1 and s2 so i concluded that the order of occurrence of characters of s1 and s2 will be same in s3 that is LongestCommonSubsequence(s1,s3)=s1 and LongestCommonSubsequence(s2,s3)=s2 and thats why I though I could just compare the characters of s3 with stack values and pop characters if they are same (i maintained 2 stacks and pushed s1 and s2 in reverse order ) if s3 is interleaving both stacks must be empty in the end and we can return true (i have attached my code,it could be wrong but thats what i was trying to do)
i cant seem to visualize where this approach would fail, if anyone has any idea please share your thoughts I'm really struggling
thanks in advance !
bool isInterleave(string s1, string s2, string s3) {
stack<char>a,b;
for(int i=s1.length()-1;i>=0;i--){
a.push(s1[i]);
}
for(int i=s2.length()-1;i>=0;i--){
b.push(s2[i]);
}
int i=0;
while( i<s3.length()){
int flag=0;
while(!a.empty() &&i<s3.length()&& a.top()==s3[i])
{
a.pop();
i++;
flag=1;
}
while(!b.empty()&&i<s3.length()&&b.top()==s3[i]){
b.pop();
i++;
flag=1
}
if(!flag)i++;
}
return (a.empty()&&b.empty()&& i==s3.length()?true:false);
}
Related
I have worked on a bipartite matching problem, and I obviously got a trouble to solve it.
Let me tell you what the problem is about.
As an input form, it gives me N, M which is the number of people at the work and the number of different kind of jobs in the work.
In the following N lines, it tells us s that tells how many kind of job that ith person can do. In the following s numbers, they will tell us that which jobs can ith person can do. The number of the jobs si will satisfy 1<=si<=M.
Then, if each person can work on only one or less job at a time, how many jobs can be done at most?
This is the problem, and I hope this made sense for you;) I apologize my poor english skill. Returning to the point, this is my code.
#include <stdio.h>
int n, m, dfscheck[1003], check[1003], input[1003][1003], back[1003], tmp, count=0;
void dfs(int num)
{
int i, j;
if(check[num]==0)
{
tmp=-1;
check[num]=1;
return;
}
if(dfscheck[num]==1)
return;
dfscheck[num]=1;
for(j=1; j<=input[back[num]][0]; j++)
{
dfs(input[back[num]][j]);
if(tmp==-1)
{
back[input[back[num]][j]]=back[num];
return;
}
}
}
int main(void)
{
int i, j, flag ,k;
scanf("%d %d", &n, &m);
for(i=1; i<=n; i++)
{
scanf("%d", &input[i][0]);
for(j=1; j<=input[i][0]; j++)
scanf("%d", &input[i][j]);
}
for(i=1; i<=n; i++)
{
flag=0;
for(j=1; j<=input[i][0]; j++)
if(check[input[i][j]]==0)
{
check[input[i][j]]=1;
count++;
flag=1;
back[input[i][j]]=i;
break;
}
if(flag==0)
for(j=1; j<=input[i][0]; j++)
{
for(k=0; k<=1001; k++)
dfscheck[k]=0;
tmp=0;
dfs(input[i][j]);
if(tmp==-1)
{
back[input[i][j]]=i;
count++;
}
}
}
printf("%d", count);
return 0;
}
The name of tmp is really bad to understand code, so... tmp works like a flag in the function dfs. It tells whether it has found a matching.
I got wrong answer, neither runtime error nor time exceed. I have read several different codes that others have written, and I couldn't find which part is wrong in my code.
I have found that my code is distinct from others' in the part that I don't define a array, A[i], showing which job is matched to ith person, exactly opposite to Back array in my code. As far as I understood their codes, the purpose of it is to find out ith person has already been matched before we get into dfs. I don't think this case can be happened. Since no flow has come out of the node of ith person, it is impossible for a flow to go from a node of jobs to the node in max flow.
I wanted to say my thoughts even if it is useless, just in case that it helps you give me some advices. Anyway, let me have your opinions!!!
Thank you so much for your time.
One thing that looks weird is:
if(tmp==-1)
{
back[input[i][j]]=i;
count++;
// I would expect to see "break;" here
}
if you find a way to assign person i to a job you increment the count, and then carry on trying to see if you can find an alternative way to assign the same person. This means that you may end up assigning the same person to multiple jobs!
I recommend inserting a "break;" statement once you have found a job for the person.
My Q is similar to the one asked on stack overflow in the past
http://www.geeksforgeeks.org/dynamic-programming-set-32-word-break-problem/
The solution I wrote, I am not able to understand that since I do not use DP but still how is it that my sol is solving overlapping problems. I think it is not. Can someone clarify?
my dicitonary that i use is {"cat", "catdog", "dog", "mouse"} and test string as "catdogmouse"
Here is the method i wrote
public static boolean recursiveWordBreak2(String s, int start) {
System.out.println("s is:"+s.substring(start));
if (s.isEmpty() || start >= s.length()) {
return true;
}
for (int i = start; i <= s.length(); i++) {
String str = s.substring(start, i);
System.out.println("substr:" + str);
if (dictSet.contains(str)) {
return recursiveWordBreak2(s, i);
}
}
return false;
}
Your solution uses recursion -only-. recognising that that problem is DP allows you to MEMOIZE (remember) previous results so that you can reuse them without doing the recursion again.
in the link you provided if the dictionary is {a,b,c,d,e} and the input is "abcde", you would need to check if "cde" is valid twice with recursive code, where a DP solution would remember "cde" is valid and only have to check once.
edit: dictionary {a,b,c,d,e} should be {a, ab, cde} to illustrate checking 'cde' twice
edit2 (see comment on algo having logic issue):
if (dictSet.contains(str)) {
return recursiveWordBreak2(s, i);
}
should be
if (dictSet.contains(str) && recursiveWordBreak2(s, i)) { return true }
that way if contains = true but recursiveWB = false, the outer loop will continue to check length+1 instead of returning false
int main() {
std::string str;
str.reserve(9999);
{
std::string s1("aaa");
std::string s2("bbb");
// can both strings s1, s2 be moved to str?
// for example str should be "aaabbb"
}
}
My question: is it possible to steal the memory of s1 and s2 to form a concatenated string of s1 and s2 (since it already has enough space for both)?
Because the memory used for a std::string has to be contiguous, there can't be a way to steal the memory of two independent strings.
From C++14, section 21.4.1/4:
The char-like objects in a basic_string object shall be stored contiguously. That is, for any basic_string
object s, the identity &*(s.begin() + n) == &*s.begin() + n shall hold for all values of n such that 0
<= n < s.size().
Please tell me why this code is giving garbage values
Compiles well, implemented this based on the Cormen algorithm for mergesorting
Basically taking given numbers in a dynamic array. two void functions are taken.One is to merge the two sub arrays via merge sort and the other to recursively split the array to sub arrays
#include<iostream>
using namespace std;
void merge(int *A,int p, int q, int r)// a function to merge two //sub arrays
{
int n1= q-p+1;
int n2=r-q;
int L[n1];
int R[n2];
for (int i=0;i<n1;i++)
{
L[i]=A[p+i];
}
int m=1;
for(int j=0; j<n2 ;j++)
{
R[j]=A[q+m];
m=m+1;
}
int i=0;
int j=0;
for(int k=0;k<r;k++)
{
if (L[i]<=R[j])
{
A[k]=L[i];
i=i+1;
}
else
{
A[k]=R[j];
j=j+1;
}
}
}
void mergesort(int *A,int p,int r)// dividng the sequence to sub arrays
{
if (p<r)
{
int q;
q=(p+r)/2;
mergesort(A,p,q);
mergesort(A,(q+1),r);
merge(A,p,q,r);
}
}
int main()
{
int n;
cout<<"Enter the number of numbers to be sorted by merge sort"<<endl;
cin>>n;
int* a=NULL;
a=new int[n];
int temp;
cout<<"Enter the numbers"<<endl;
for(int i=0;i<n;i++)
{
cin>>temp;
*(a+i)=temp;// inputting the given numbers into a dynamic array
}
cout<<"The given numbers are:"<<endl;
for(int j=0;j<n;j++)
cout<<*(a+j)<<" ";
mergesort(a,0,n-1);
cout<<"The merged sorted numbers are:"<<endl;
for(int s=0;s<n;s++)
cout<<*(a+s)<<" ";
delete [] a;
system("pause");
return 0;
}
You are getting your intervals wrong pretty much everywhere in your code. For example:
Based on your usage in main, mergesort is supposed to sort the sublist of indices [0,n-1].
With this meaning, your recursion in mergesort says in order to sort the indices [p,r-1], you should first sort [p,q-1] then sort [q+1,r-1]: you completely ignore index q.
Similarly, merge is confused: once you fix the typo when coping into L (A[i] should be A[p+i]), it takes [p,q] as one list, and [q,r] as the other list: note you copy entry q twice, and you also copy r when you probably shouldn't be.
To fix your code, you need to straighten out exactly what intervals everything is supposed to be working on. This isn't a hard problem, you just have to bring yourself to write down explicitly exactly what all of your functions and loops and stuff are supposed to be doing.
The typical convention these days is half-open intervals: you should generally think of taking indices [p,q) from a list. ([p,q) is the same as [p,q-1]) Here are several examples of why this is preferred:
The number of entries of [p,r) is simply r-p
A for loop iterating through [p,r) is the usual for(i=p; i<r; ++i) (not <=)
Splitting the interval [p,r) into parts gives you intervals [p,q) and [q,r) -- there is no worry about remembering to add 1 in places.
e.g. merge would normally be designed to take the first list comes from indices [p,q) and the second list from indices [q,r).
I am looking for the most efficient algorithm to form all possible combinations of words from a string. For example:
Input String: forevercarrot
Output:
forever carrot
forever car rot
for ever carrot
for ever car rot
(All words should be from a dictionary).
I can think of a brute force approach. (find all possible substrings and match) but what would be better ways?
Use a prefix tree for your list of known words. Probably libs like myspell already do so. Try using a ready-made one.
Once you found a match (e.g. 'car'), split your computation: one branch starts to look for a new word ('rot'), another continues to explore variants of current beginning ('carrot').
Effectively you maintain a queue of pairs (start_position, current_position) of offsets into your string every time you split the computation. Several threads can pop from this queue in parallel and try to continue a word that starts from start_position and is already known up to current_position of the pair, but does not end there. When a word is found, it is reported and another pair is popped from the queue. When it's impossible, no result is generated. When a split occurs, a new pair is added to the end of the queue. Initially the queue contains a (0,0).
See this question which has even better answers. It's a standard dynamic programming problem:
How to split a string into words. Ex: "stringintowords" -> "String Into Words"?
A psuedocode implementation, exploiting the fact that every part of the string needs to be a word, we can't skip anything. We work forward from the start of the string until the first bit is a word, and then generate all possible combinations of the rest of the string. Once we've done that, we keep going along until we find any other possibilities for the first word, and so on.
allPossibleWords(string s, int startPosition) {
list ret
for i in startPosition..s'length
if isWord(s[startPosition, i])
ret += s[startPostion, i] * allPossibleWords(s, i)
return ret
}
The bugbear in this code is that you'll end up repeating calculations - in your example, you'll end up having to calculate allPossibleWords("carrot") twice - once in ["forever", allPossibleWords["carrot"]] and once in ["for", "ever", allPossibleWords["carrot"]]. So memoizing this is something to consider.
Input String: forevercarrot
Output:
forever carrot
forever car rot
for ever carrot
for ever car rot
program :
#include<iostream>
#include<string>
#include<vector>
#include<string.h>
void strsplit(std::string str)
{
int len=0,i,x,y,j,k;
len = str.size();
std::string s1,s2,s3,s4,s5,s6,s7;
char *c = new char[len+1]();
char *b = new char[len+1]();
char *d = new char[len+1]();
for(i =0 ;i< len-1;i++)
{
std::cout<<"\n";
for(j=0;j<=i;j++)
{
c[j] = str[j];
b[j] = str[j];
s3 += c[j];
y = j+1;
}
for( int h=i+1;h<len;h++){
s5 += str[h];
}
s6 = s3+" "+s5;
std::cout<<" "<<s6<<"\n";
s5 = "";
for(k = y;k<len-1;k++)
{
d[k] = str[k];
s1 += d[k];
s1 += " ";
for(int l = k+1;l<len;l++){
b[l] = str[l];
s2 += b[l];
}
s4 = s3+" "+s1+s2;
s7 = s4;
std::cout<<" "<<s4<<"\n";
s3 = "";s4 = "";
}
s1 = "";s3 = "";
}
}
int main(int argc, char* argv[])
{
std::string str;
if(argc < 2)
std::cout<<"Usage: "<<argv[0]<<" <InputString> "<<"\n";
else{
str = argv[1];
strsplit(str);
}
return 0;
}