CCF 2019-12 third question chemical equation balancing

Keywords: iOS less




Explanation:

String emulation
The meaning of the question is to judge whether the chemical equation is balanced.
Basic idea: count the elements on the left and right side of the chemical equation, and then judge whether all elements are equal.
   step 1: split the string
                      
                       
   the second step: to extract the outermost multiple of the chemical formula, such as 3H2O, you need to extract 3, and you need to multiply all the internal elements by 3.
Step 3: why use dfs to treat a chemical formula alone? Because of the nesting of parentheses in the formula, dfs is required to handle each parenthesis separately. Note that the multiple needs to be recorded. The next time the multiple is calculated, it is passed in. Each count needs to process the multiple.
Details:
   1. The element is a capital or a capital and a lowercase
   2. Nesting of multiple brackets
   3. The number after the bracket needs to be converted to multiple input
4. Always pay attention to prevent crossing
5. Judge the empty string separately

Complexity analysis: a string is scanned once as O(len). Because of the parentheses, the string needs to be cut. The complexity of string cutting is O(len), so the processing complexity of each string is O(len2), the map complexity is O(mlog2(m)) less than O(len2), and the complexity is larger. N strings, the total complexity is O(n(len2))

Code (with comments):

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false)
#define ll long long
#define maxn 1005
#define inf 1000000000

//Split string with sp separator
vector<string> split_str(string str,char sp)
{
    vector<string>V;
    for(int i=0; i<str.size();)
    {
        string ss="";
        while(i<str.size()&&str[i]!=sp)
        {
            ss.push_back(str[i]);
            i++;
        }
        i++;
        if(ss!="")
            V.push_back(ss);
    }
    return V;
}

//Convert a number in string form to Int
int get_num(string num)
{
    int num1=0;
    int ten=1;
    for(int k=num.size()-1; k>=0; k--)
    {
        num1+=(num[k]-=48)*ten;
        ten*=10;
    }
    return num1;
}

/**
    Count the individual formula:
    Use dfs to disassemble the bracket and record the multiple of each record at the same time
    For those not in brackets, just count directly (multiply by multiple of course)
    For example, 4AL(Au(CN)2)3 the next dfs will pass in Au(CN)2 by multiple 3
**/
void dfs(map<string,int>&m1,string str,int num1)
{
    for(int k=0; k<str.size();)
    {
        if(str[k]=='(')
        {
            k++;
            int num_c=1,num_f=0;
            int j;
            for(j=k; j<str.size(); j++)
            {
                if(str[j]=='(')
                    num_c++;

                if(str[j]==')')
                {
                    num_f++;
                    if(num_f==num_c)
                        break;
                }
            }

            int len=j-k;

            string num="";
            j++;
            for(; j<str.size(); j++)
            {
                if(str[j]>='0'&&str[j]<='9')
                    num.push_back(str[j]);
                else
                    break;
            }
            int num2=1;
            if(num!="")
                num2=get_num(num);
            //cout<<"k="<<k<<",len="<<len<<",str="<<str.substr(k,len)<<",num1="<<num1*num2<<"\n";
            dfs(m1,str.substr(k,len),num1*num2);
            //cout<<num<<"\n";
            k+=len+num.size()+1;
            //cout<<"k="<<k<<"\n";
        }
        else
        {
            string xx="";
            xx.push_back(str[k]);

            if(k+1<str.size()&&str[k+1]>='a'&&str[k+1]<='z')
            {
                xx.push_back(str[k+1]);
                k++;
            }
            k++;
            string num="";
            while(k<str.size()&&str[k]>='0'&&str[k]<='9')
            {
                num.push_back(str[k]);
                k++;
            }
            int num2=1;
            if(num!="")
                num2=get_num(num);

            m1[xx]+=num2*num1;
        }
    }
}

/**
    1,Deal with the left or right side of a chemical equation
    2,The initial multiple of the treatment formula, such as 4AL(Au(CN)2)3, is the first 4
    3,Treat each chemical formula dfs separately
**/
void get_map(map<string,int>&m1,vector<string>&V1)
{
    for(int j=0; j<V1.size(); j++)
    {
        string strid=V1[j];
        string num="";
        for(int k=0; k<V1[j].size(); k++)
        {
            if(V1[j][k]>='0'&&V1[j][k]<='9')
                num+=V1[j][k];
            else
                break;
        }
        int num1;
        if(num!="")
        {
            reverse(V1[j].begin(),V1[j].end());
            for(int k=0; k<num.size(); k++)
                V1[j].pop_back();
            reverse(V1[j].begin(),V1[j].end());
            //cout<<V1[j]<<" ";
            num1=get_num(num);
        }
        else
            num1=1;

        dfs(m1,V1[j],num1);

    }
}

//Determine whether two map s are equal
bool equal_map(map<string,int>&m1,map<string,int>&m2)
{
    return m1==m2;
}

//Print map
void print_map(map<string,int>&m1)
{
    for(map<string,int>::iterator p=m1.begin(); p!=m1.end(); p++)
        {
            cout<<(*p).first<<","<<(*p).second<<"\n";
        }
    cout<<"---------------\n";
}

int main()
{
    IOS;
    ll n;
    cin>>n;

    for(int i=1; i<=n; i++)
    {
        map<string,int>m1,m2;

        string str;
        cin>>str;
        vector<string>V=split_str(str,'=');
        vector<string>V1=split_str(V[0],'+');
        vector<string>V2=split_str(V[1],'+');
        get_map(m1,V1);
        get_map(m2,V2);
        /*cout<<"m1:\n";
        print_map(m1);
        cout<<"m2:\n";
        print_map(m2);*/
        if(equal_map(m1,m2))
            cout<<"Y\n";
        else
            cout<<"N\n";
    }
    return 0;
}

Postscript: this question has been modeled for two hours, and the CCF big simulation question is indeed worthy of its name

Published 41 original articles, won praise 2, visited 1178
Private letter follow

Posted by amir on Fri, 24 Jan 2020 01:13:47 -0800