题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=542
解题思路:
省赛的时候就是卡在这里,没能搞出来。
下来又仔细想了下,然后很快就把代码打出来了。。。。字符串处理还是不行,以后多练吧。。。。。。
我的思路就是用字典树存化学物,然后查反应物是否齐全,齐全的话看是否是反应物,如果不是反应物就加入一个结果数组。之后排序一下就可以了。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
char word[410][110];
bool visit[410];
string ans[10010]; //生成物
int top;
struct trie
{
int flag, size; //单词存在、反应物or生成物
trie* next[65];
trie():flag(0), size(-1){
memset(next, NULL, sizeof(next));
}
}*head;
void insert(string s, int type)
{
int temp, len;
trie* cur = head;
len = s.length();
for(int i = 0; i < len; ++i)
{
if(s[i] >= 'a' && s[i] <= 'z')
temp = s[i] - 'a';
else if(s[i] >= 'A' && s[i] <= 'Z')
temp = (int)(s[i] - 'A') + 26;
else
temp = (int)(s[i] - '0') + 52;
if(cur->next[temp] == NULL)
cur->next[temp] = new trie;
cur = cur->next[temp];
}
cur->flag = 1;
if(type == 0)
cur->size = 0; //反应物
else
{
if(cur->size == -1)
{
cur->size = 1;
ans[top++] = s;
}
}
}
int find(char* s)
{
int i, len = strlen(s);
for(i = 0; i < len; ++i)
if(s[i] == '=')
return i;
}
bool query(string s)
{
int len, temp;
len = s.length();
trie* cur = head;
for(int i = 0; i < len; ++i)
{
if(s[i] >= 'a' && s[i] <= 'z')
temp = s[i] - 'a';
else if(s[i] >= 'A' && s[i] <= 'Z')
temp = (int)(s[i] - 'A') + 26;
else
temp = (int)(s[i] - '0') + 52;
if(cur->next[temp] == NULL)
return false;
cur = cur->next[temp];
}
if(cur->flag == 1)
return true;
else
return false;
}
int main()
{
int num, have;
string now;
int pos; //等号的位置
string temp;
while(scanf("%d", &num) != EOF)
{
head = new trie;
memset(word, '\0', sizeof(word));
memset(visit, false, sizeof(visit));
top = 0;
for(int i = 0; i < num; ++i)
scanf("%s", word[i]);
scanf("%d", &have);
for(int i = 0; i < have; ++i)
{
cin>>now;
insert(now, 0);
}
while(true)
{
int out = 1;
for(int i = 0; i < num && !visit[i]; ++i) //处理化学式
{
bool flag = true; //可以发生反应
int len = strlen(word[i]);
pos = find(word[i]);
for(int j = 0; j <= pos; ++j) //前半部分
{
if(word[i][j] != '+' && word[i][j] != '=')
temp += word[i][j];
else //找到一个完整单词
{
flag = query(temp);
temp.clear();
if(flag == false) //缺少反应物
break;
}
}
if(flag == true) //发生反应
{
visit[i] = true;
out = 0;
for(int j = pos + 1; j <= len; ++j)
{
if(word[i][j] != '+' && word[i][j] != '\0')
temp += word[i][j];
else
{
insert(temp, 1);
temp.clear();
}
}
}
else
continue;
}
if(out == 1)
break;
}
sort(ans, ans + top);
printf("%d\n", top);
for(int i = 0; i < top; ++i)
cout<<ans[i]<<endl;
}
return 0;
}