#include <iostream>
#include <set>
#include <string>
using namespace std;
int main()
{
set<string> str1; //储存字符串片段
set<string> str2; //储存不同字符串
set<string> str4; //储存不同字符串中不是前缀的
string str[1001];
string sts[1001]; //储存相同字符串
int n, i, k, l1 = 0, sign = 0;
string in1, in2;
set<string>::iterator it1;
set<string>::iterator it2;
cin >> n;
for(i = 0; i < n; i++)
{
cin >> in1;
//判断是否是str2已存在的字符
if(str2.insert(in1).second == false)
{
str[l1] = in1; //输入的相同字符
l1++;
}
else
{
str2.insert(in1); //输入的不同字符
//对于不同字符进行拆解
for(k = 1; k < in1.size(); k++)
{
in2.assign(in1.c_str(), k);
str1.insert(in2); //每一种拆解后的字符串片段
}
}
}
int flog;
for(it2 = str2.begin(); it2 != str2.end(); it2++)
{
flog = 0;
// cout << *it2 << endl;
for(it1 = str1.begin(); it1 != str1.end(); )
{
if(*it1 == *it2)
{
flog = 1;
sign++;
break;
}
else
it1++;
}
if(flog == 0)
str4.insert(*it2);
}
set<string>::iterator it4;
int x = 0;
for(i = 0; i < l1; i++)
{
for(it4 = str4.begin(); it4 != str4.end(); it4++)
{
if(str[i] == *it4)
{
sts[x] = *it4;
x++;
break;
}
}
}
l1 -= x;
sign += l1 + 2 * x;
cout << sign << endl;
return 0;
}
上面是我写的,下面是师哥写的。。。
正确的:
#include<set>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXN = 1000+10;
int vis[1000+10];
int main()
{
int n, ans = 0;
string s[MAXN];
scanf("%d", &n);
set<string> ss;
memset(vis, 0, sizeof(vis));
for(int i = 0; i < n; i++){
cin>>s[i];
for(int k = 1; k < s[i].length(); k++){
if(!ss.count(s[i].substr(0,k)))
ss.insert(s[i].substr(0,k));
}
}
for(int i = 0; i < n; i++){
if(ss.count(s[i])){
ans++;
vis[i] = 1;
}
}
for(int i = 0; i < n; i++){
if(vis[i] == 1)
continue;
for(int j = 0 ; j < n ; j++){
if(i == j)
continue ;
if(s[i] == s[j]){
ans++;
break;
}
}
}
printf("%d\n",ans);
return 0;
}
其中count函数和substr函数是十分重要的:
count:
count(目标串,目标串+n(想找的范围), x(找哪个) )
这个函数用来判断x在目标串中出现的次数;
sunstr:
str.sunstr(x,y)
这个函数用来取str中从x到y之间的字符。
最近看了前缀树,感觉用前缀树也能做。