国际大学生程序设计竞赛例题_1.1 信息泛滥

题目大意:
n m
n:n行字符串(长度<10)
m:m行字符串
结果:去掉m中含有的n中的字符串,返回n中剩余的个数.

解答1:
建立一个字典树,统计节点中1的个数.

#include <stdio.h>

//定义字典树
struct tree
{
tree():bj(0)
{
for(int i=0;i<26;i++)
node[i]=NULL;
}

tree* node[26]; //子节点
int bj; //标识根到该节点是否对应某个字串
}* root;

void update(char* s) //对大小写不敏感,统一转化为小写
{
while(*s) *s|=32,s++;
}

int n,m;
int ans; //保存结果.
char s[11];//输入的字串

//bj为1:插入字串
//bj为0:删除字串
void visit(tree* p,char* s,int bj) //遍历并更新字典树
{
char c=(*s)-'a'; //char类型,可以节省内存
if(p->node[c]) p=p->node[c]; //转移根节点
else
{
if(!bj) return; //要删除的字串不存在
p->node[c]=new tree; //新建一个叶子节点
p=p->node[c];//转移根节点
}
if(s[1]) visit(p,s+1,bj); //递归遍历下一个字符
else
{
if(p->bj!=bj) ans+=(bj? 1:-1);
//若是bj原来是1,现在为0,意味着删除,ans-1
//反之,意味着插入,ans+1
//相同:重复插入或是删除一个已经删除过的
p->bj=bj;
}

}

void release(tree* p)
{
for(int i=0;i<26;i++)
if(p->node[i]) release(p->node[i]);
delete p;
}


int main()
{
freopen("1.1.in","r",stdin);
int i;

while(scanf("%d %d",&n,&m),n) //这么写:输入0表示测试结束
{
root=new tree;
ans=0;
for(i=0;i<n;i++)
{
scanf("%s",s);
update(s);
visit(root,s,1); //插入操作
}

for(i=0;i<m;i++)
{
scanf("%s",s);
update(s);
visit(root,s,0); //删除操作
}
printf("%d\n",ans);
release(root);
}
return 0;
}


解答2:
利用STL中的set.

#include <iostream>
#include <set>
#include <string>

using namespace std;

void update(string& s)
{
for(int i=0;i<s.size();i++)
s[i]|=32;
}

int main()
{
string s;
int n,m;
int ans;
freopen("1.1.in","r",stdin);
int i;
set<string> setStr;
set<string>::iterator ite;
while(cin>>n>>m,n) //这么写:输入0表示测试结束
{
ans=0;
setStr.clear();
for(i=0;i<n;i++)
{
cin>>s;
update(s);
setStr.insert(s);
}


for(i=0;i<m;i++)
{
cin>>s;
update(s);
ite=setStr.find(s);
if(ite!=setStr.end())
setStr.erase(ite);
}
cout<<setStr.size()<<endl;
}
return 0;
}


注:附件中为测试数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值