NAME1 - Editorial

PROBLEM LINKS

Practice
Contest

DIFFICULTY

CAKEWALK

PREREQUISITES

Ad-Hoc

PROBLEM

You are given two strings A and B. You are also given N strings C1, C2, … CN.

Let C = C1 + C2 + … CN
where + is the concatenation operator (note that it is not commutative)

Find whether C may be a substring of one of the permutations of A + B.

QUICK EXPLANATION

The length of A + B can be 80000. Of course, we cannot possibly generate all the permutations of A + B. Let us use some insight.

Lemma: If C is a substring of a permutation of A + B, then there is a permutation of A + B in which C is a prefix.

It is easy to see that if C exists as a substring, we can shift all the characters on the left of the first occurance of C, to the end of the string without affecting the presence of C in the permutation of A + B. Also, if C is a prefix of some permutation of A + B, then it is also a permutation which is proof enough to return a positive answer.

Lemma: If there is no permutation of A + B such that C is a prefix, then there is no permutation of A + B such that C is a substring.

This is easily proven by contradiction. If we assume that there is a permutation of A + B in which C is a substring, then by the previous Lemma we should have a permutation of A + B in which C is a prefix. Thus our assumption cannot be true.

From the above two, we can clearly say

C can be a substring of some permutation of A + B iff there is a permutation of A + B of which C is a prefix.

EXPLANATION

Since we have the liberty to assume any permutation of A + B, we can treat it as a bag of characters and just try to build a permutation with C as prefix. If we are unable to, then of course we return negative. Otherwise, we can successfully have C as a substring by letting the other characters occupy any position on the left or right of the constructed string C (from characters in A + B).

We can build a count of all the characters in A + B as follows

counts[a ... z] = { 0 }

for each character c in A
    counts[c]++
for each character c in B
    counts[c]++

We can construct C by concatenating the given strings. The statement assures us that the length of C is not more than the length of A + B. Then we can one by one reduce the count of the characters in C. If any of the counts become negative, then we know that we cannot choose that character and that C cannot exist as a prefix (as well as substring) of any permutation of A + B.

for each chatacter c in C
    counts[c]--
    if counts[c] < 0
        return false

return true

The complexity of the algorithm is O(|A| + |B| + |C|).

SETTER’S SOLUTION

Can be found here.

TESTER’S SOLUTION

Can be found here.

1 Like

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

map <char,int> p;
map <char,int> ci;
map <char,int> :: iterator ptr1,ptr2;

void par(string parent){
p.insert(pair<char,int> (parent[0],1));
int i,flag = 0;
for(i = 1; i<parent.length(); i++){
flag = 0;
for(ptr1 = p.begin(); ptr1 != p.end(); ptr1++){
if(ptr1->first == parent[i]){
(ptr1->second)++;
flag = 1;
break;
}
}
if(flag == 0)
p.insert(pair<char,int>(parent[i],1));
}
}

void chi(string parent){
ci.insert(pair<char,int> (parent[0],1));
int i,flag = 0;
for(i = 1; i<parent.length(); i++){
flag = 0;
for(ptr1 = ci.begin(); ptr1 != ci.end(); ptr1++){
if(ptr1->first == parent[i]){
(ptr1->second)++;
flag = 1;
break;
}
}
if(flag == 0)
ci.insert(pair<char,int>(parent[i],1));
}
}

void solve(string parent, string child){
par(parent);
chi(child);
int flag = 0;
for(ptr1 = ci.begin(); ptr1 != ci.end(); ptr1++){
for(ptr2 = p.begin(); ptr2 != p.end(); ptr2++){
if(ptr2->first == ptr1->first)
if(ptr1 -> second > ptr2 -> second){
flag = 1;
break;
}
}
if(flag == 1)
break;
}
flag == 1 ? cout<<“NO”<<endl:cout<<“YES”<<endl;
}

int main() {
// your code goes here
int t;
cin>>t;
while(t–){
string a,b;
fflush(stdin);
cin>>a>>b;
fflush(stdin);
string parent = a+b;
int n,i;
cin>>n;
string c[n];
for(i = 0; i<n; i++){
fflush(stdin);
cin>>c[i];
fflush(stdin);
}
string child;
for(i = 0; i<n; i++)
child = child + c[i];
if(child.length() > parent.length())
cout<<“NO”<<endl;
else
solve(parent,child);
p.clear();
ci.clear();
}
return 0;
}

Someone please tell me what’s wrong with this code (it is passing the given test cases). The concept I used is that I counted the frequency of each character in child string (c1+c2+ … ) if the frequency is less than or equal to the frequency of those characters in parent string (a+b), then YES else NO. Thanks in advance. :slightly_smiling_face:

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

int main() {
int t;
cin>>t;
while(t–){
string A,B;
cin>>A>>B;
map<char,int>m;
for(int i=0;i<A.size();i++){
m[A[i]]++;
}
for(int i=0;i<B.size();i++){
m[B[i]]++;
}

    int n,p=0;
    cin>>n;
    vector<string>s(n);
    map<char,int>mp;
    for(int i=0;i<n;i++){
        cin>>s[i];
        
        for(int j=0;j<s[i].size();j++){
            mp[s[i][j]]++;
        }
    }
    
  
    for(auto it:mp){
        int k=it.second;
        char c=it.first;
        if(m.find(c)!=m.end()){
            if( m[c]>=k){
                p=1;
            }
            else {
                p=0;
                break;
            }
        }
        else{
            p=0;
            break;
        }
            
        
    }
    if(p==1){
        cout<<"YES"<<endl;
    }
    else cout<<"NO"<<endl;
    
}
// your code goes here
return 0;

}