洛谷P1808 单词分类_NOI导刊2011提高(01) 字符串排序
洛谷P1808 单词分类_NOI导刊2011提高(01)
题目描述
Oliver为了学好英语决定苦背单词,但很快他发现要直接记住杂乱无章的单词非常困难,他决定对单词进行分类。
两个单词可以分为一类当且仅当组成这两个单词的各个字母的数量均相等。
例如“AABAC”,它和“CBAAA”就可以归为一类,而和“AAABB”就不是一类。
现在Oliver有N个单词,所有单词均由大写字母组成,每个单词的长度不超过100。你要告诉Oliver这些单词会被分成几类。
输入格式
输入文件的第一行为单词个数N,以下N行每行为一个单词。
输出格式
输出文件仅包含一个数,表示这N个单词分成的类数
输入输出样例
输入 #1
3 AABAC CBAAA AAABB
输出 #1
2
说明/提示
对于70%的数据满足N≤100。 对于100%的数据满足N≤10000。
Solution
Algorithm(1)
对每一个字符串自身进行一次内部排序
再对所有字符串进行排序
初始化ans=1;因为至少会有一类的
枚举所有字符串,若str[i]!=str[i+1],ans++;
最后输出ans
最多运算次数:
100*log(100)*10000+10000*log(10000)+10000
约等于O(nlog(n))吧?
Code(100分)
事实证明这还是能过的
并不需要后面的更为复杂的算法
1 #include<iostream>//不想OI一场空,千万别用万能头 2 #include<algorithm>//快排sort() 3 #include<cstring> 4 using namespace std; 5 bool cmpchar(char ta,char tb){ 6 return ta<tb; 7 } 8 bool cmpstr(string ta,string tb){ 9 return ta<tb; 10 } 11 string word[10001]; 12 int n; 13 int main() 14 { 15 cin>>n; 16 int ans=1; 17 for(int i=0;i<n;i++){ 18 cin>>word[i]; 19 sort(&word[i][0],&word[i][word[i].size()],cmpchar); 20 } 21 sort(&word[0],&word[n],cmpstr); 22 for(int i=0;i<n-1;i++) 23 if(word[i]!=word[i+1]) 24 ans++; 25 cout<<ans; 26 return 0; 27 }
其思想就是:分类找间隔,类数=间隔+1
ALgorithm(2)
借用STL<map>
map,可以把它当成是一个自定义数组
map<string,bool>word
就是新建一个数组
名为word
下表是string类型的
值则是bool类型的
而且可以像普通数组那样直接访问
word[str]==1;
Code(100分)
1 #include<iostream>//不想OI一场空,千万别用万能头 2 #include<algorithm>//快排sort() 3 #include<cstring> 4 #include<cstdio> 5 #include<map> 6 using namespace std; 7 map<string,bool>word; 8 int n,ans; 9 string t; 10 int main() 11 { 12 scanf("%d",&n); 13 for(int i=0;i<n;i++) 14 { 15 cin>>t; 16 sort(t.begin(),t.end()); 17 if(!word[t]) 18 { 19 ans++; 20 word[t]=1; 21 } 22 } 23 cout<<ans; 24 return 0; 25 }
哈哈哈,sort还能这样用哟!
str.begin() str.end()会返回str首尾的地址
这比
sort(&word[i][0],&word[i][word[i].size()],cmpchar);
好用多了吧?
STL大法好!