版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yixin94/article/details/83041025
题意:给出一个化合物的化学式 eg, Mg(OH)2 and K4(ON(SO3)2)2,统计出其每个原子的个数
很明显用递归做,如果遇到a(bcd)ef,则bcd构成一个子问题,递归处理统计出各个原子出现的频率(用map记录),如果e是个数字,返回后merge频率乘上该数字即可。
但是需要保证先处理外面的括号,再处理内部的括号e.g., (a(bdc)e)。我把一块当做merge inteval处理了,但感觉没必要,因为不会出现([)]的情况。用栈可以得出所有括号匹配的区间,merge interval之后得到的区间都是最外层的。e.g., (ab)c(de), a(bc[内部的括号在子问题中再处理]d)e。
另外统计括号外部的原子频率时,需要跳过括号内部的部分。可以Maintain一个cnt,遇到区间左端点+1,遇到区间右端点-1,cnt=0则表示区间之外。
wa了几次都是merge interval最初或者最后忘记记录interval了。另外数字可能不是一位数。
复杂度是N^2,因为每个字母只会访问一次,处理(abc)之后如果原先的(abc)d中d是数字,则需要O(N)去计算merge之后的频率。
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
#include<stack>
using namespace std;
//leetcode 726. Number of Atoms
const int maxn=1010;
int T;
int N;
int M;
class Solution {
public:
//save the branket position left is i, right is pos[i]
string countOfAtoms(string formula) {
cout<<formula<<endl;
map<string,int>mp=dfs(0,formula.length(),formula);
string ret;
for(auto iter=mp.begin();iter!=mp.end();iter++)
{
ret+=iter->first;
if(iter->second!=1)
{
int tmp=iter->second;
string s="";
while(tmp!=0)
{
s+=(tmp%10)+'0';
tmp/=10;
}
reverse(s.begin(),s.end());
ret+=s;
}
cout<<iter->first<<" "<<iter->second<<endl;
}
return ret;
}
map<string,int> dfs(int st,int ed,string formula)
{
// cout<<st<<" start dfs "<<ed<<endl;
int pos[maxn];
memset(pos,0,sizeof(pos));
map<string,int>mp;
stack<int>sta;
vector<pair<int,int> >interval;
vector<pair<int,int> >merged_interval;
for(int i=st;i<ed;i++)
{
if(formula[i]=='(')
{
sta.push(i);
}
if(formula[i]==')')
{
int tmp=sta.top();
sta.pop();
interval.push_back(make_pair(tmp,i));
}
}
if(interval.size()!=0)
{
sort(interval.begin(),interval.end());
int interval_st=interval[0].first;
int interval_ed=interval[0].second;
pos[interval_st]=1;
pos[interval_ed]=-1;
for(int i=0;i<interval.size();i++)
{
// cout<<"interval "<<interval[i].first<<" "<<interval[i].second<<endl;
if(interval_ed<interval[i].second)
{
merged_interval.push_back(make_pair(interval_st,interval_ed));
interval_st=interval[i].first;
interval_ed=interval[i].second;
pos[interval_st]=1;
pos[interval_ed]=-1;
}
else
{
interval_ed=max(interval_ed,interval[i].second);
}
}
merged_interval.push_back(make_pair(interval_st,interval_ed));
pos[interval_st]=1;
pos[interval_ed]=-1;
}
// cout<<merged_interval.size()<<endl;
for(int i=0;i<merged_interval.size();i++)
{
// cout<<"merged interval "<<merged_interval[i].first<<" "<<merged_interval[i].second<<endl;
map<string,int>mp2=dfs(merged_interval[i].first+1,merged_interval[i].second,formula);
int prod=1;
int idx=merged_interval[i].second+1;
// cout<<formula<<endl;
if(idx<formula.length()&&formula[idx]>='0'&&formula[idx]<='9')
{
int num=0;
while(idx<formula.length()&&formula[idx]>='0'&&formula[idx]<='9')
{
// cout<<idx<<" "<<formula[idx]<<endl;
num*=10;
num+=formula[idx]-'0';
idx++;
}
// cout<<num<<endl;
prod=num;
}
for(auto iter=mp2.begin();iter!=mp2.end();iter++)
{
// cout<<"Add "<<iter->first<<" "<<iter->second<<" "<<prod<<" "<<iter->second*prod<<endl;
if(mp.find(iter->first)==mp.end())
{
mp[iter->first]=iter->second*prod;
}
else
{
mp[iter->first]+=iter->second*prod;
}
// cout<<"after add in mp "<<mp[iter->first]<<endl;
}
}
int cnt=0;
cout<<st<<" "<<ed<<endl;
for(int i=st;i<ed;i++)
{
cnt+=pos[i];
// cout<<i<<" add at end "<<formula[i]<<" "<<pos[i]<<" "<<cnt<<endl;
if(cnt==0&&formula[i]>='A'&&formula[i]<='Z')
{
string tmp=" ";
tmp[0]=formula[i];
i++;
while(i<formula.length()&&formula[i]>='a'&&formula[i]<='z')
{
tmp+=formula[i];
i++;
}
if(i<formula.length()&&formula[i]>='0'&&formula[i]<='9')
{
int num=0;
while(i<formula.length()&&formula[i]>='0'&&formula[i]<='9')
{
num*=10;
num+=formula[i]-'0';
i++;
}
mp[tmp]+=num;
// cout<<tmp<<" add "<<num<<endl;
}
else
{
mp[tmp]+=1;
// cout<<tmp<<" add 1 "<<endl;
}
i--;
}
}
// cout<<"return "<<endl;
return mp;
}
};
int main()
{
freopen("input.txt","r",stdin);
cin>>T;
for(int ca=1;ca<=T;ca++)
{
string S;
cin>>S;
cin.ignore();
Solution sol;
cout<<"Case #"<<ca<<": "<<sol.countOfAtoms(S)<<endl;
}
return 0;
}