一开始以为每个单词后都有一个空格,想得太简单了。在一些细节上总是出错,找了半天。。。
几组测试数据:
|
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e6+10;
int tr[100010][30];
int tot,ans;
bool v[100010]; //标记节点为单词
char s[maxn],str[50];
void insert()
{
int len = strlen(str);
int root = 0; //根节点编号为0
for(int i=0;i<len;i++)
{
int id = str[i]-'a'; //0~25
if(!tr[root][id]) //如果之前没有从root到id的前缀
tr[root][id] = ++tot; //插入,tot即为第一种编号
root = tr[root][id]; //顺着字典树往下走
}
v[root] = true; //将从0到root点为一个单词
}
bool find()
{
int root = 0;
for(int i=0;str[i];i++)
{
int x = str[i]-'a';
if(!tr[root][x])
return false; //没找到单词
root = tr[root][x];
}
if(v[root]) //找到单词
return true;
}
int main()
{
while(gets(s) && s[0]!='#')
{
memset(v,false,sizeof(v));
memset(tr,0,sizeof(tr));
memset(str,0,sizeof(str));
int k = 0;
int flag = 0; //是否为第一个单词
tot = 0;
ans = 0; //单词数
int n = strlen(s);
//cout<<n<<endl;
for(int i=0;i<n;i++)
{
if(s[i]>='a' && s[i]<='z')
{
str[k++] = s[i];
}
if(s[i]==' ' || i==n-1)
{
if(str[0]=='\0') //跳过连续的空格 否则会统计上
continue;
if(!flag && str[0]!='\0') //第一个单词不可能有重复的 直接插入
{
ans++;
flag = 1;
}
else if(flag) //从第二个单词开始需要检验是否存在相同单词
{
if(!find()) //不存在相同单词
ans++;
}
//cout<<str<<endl;
insert();
memset(str,0,sizeof(str)); //初始化
k = 0;
}
}
printf("%d\n",ans);
}
return 0;
}
在讨论区看到了一种简单的写法
istringstream是C++里面的一种输入输出控制类,它可以创建一个对象,然后这个对象就可以绑定一行字符串,然后以空格为分隔符把该行分隔开来。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<sstream> //istringstream 的头文件
using namespace std;
char s[100010];
int main()
{
while(gets(s) && s[0]!='#')
{
string str = s;
istringstream str1(str);
set<string> se;
while(str1>>str)
se.insert(str);
printf("%d\n",se.size());
}
return 0;
}