HDU 2072
本人做这个题目时花了太多时间,就整理汇集了见到的这几种方法。
第一种是用纯C做的:
#include<stdio.h> #include<string.h> int First_Not_Zero(char a[]); int main() { char sort_letter[100][100]; char a[1100]; while( fgets(a,1004,stdin)!=0) { if(a[0]=='#') break; if(a[0]=='\n') { printf("0\n"); continue; } int now_f=0; int now_num=0; int num=0; int k=strlen(a); a[k]='\n'; a[k-1]=' '; now_f=First_Not_Zero(a); for(int i=now_f; a[i]!='\n'; ) { if(a[i]==' ') { a[i]=NULL; int j=0; for(; j<now_num; j++) { if(strcmp(&a[now_f],sort_letter[j])==0) break; } if(j==now_num) { strcpy(sort_letter[now_num],&a[now_f]); now_num++; } i++; while(a[i]==' ') i++; now_f=i; } else i++; } printf("%d\n",now_num); } } int First_Not_Zero(char a[]) { int i=0; for(; a[i]!='\n'; i++) { if(a[i]!=' ') break; } return i;//from HDUoj }第二种(strtok):
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int main() { char s[1005],a[1005][1005]; while(gets(s)) { if(strcmp(s,"#")==0) break; int num,i,j,k,same=0; char *p; p=strtok(s," ");//strtok的函数使用 for(num=0;p!=NULL;num++) { strcpy(a[num],p);//将字符串里面的字符转移到二维数组中 p=strtok(NULL," "); } for(i=0;i<num;i++) for(j=i+1;j<num;j++) if(strcmp(a[i],a[j])==0) { same++; break; } cout<<num-same<<endl; } return 0; }
<pre name="code" class="plain"><span style="font-size:24px;">strtok</span>(百科)分解字符串为一组字符串。s为要分解的字符,delim为分隔符字符(如果传入字符串,则传入的字符串中每个字符均为分割符)。首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL。原型编辑char *strtok(char s[], const char *delim);功能编辑分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。例如:strtok("abc,def,ghi",","),最后可以分割成为abc def ghi.尤其在点分十进制的IP中提取应用较多。说明编辑strtok()用来将字符串分割成一个个片段。参数s指向欲分割的字符串,参数delim则为分割字符串中包含的所有字符。当strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回指向被分割出片段的指针。返回值编辑从s开头开始的一个个被分割的串。当s中的字符查找到末尾时,返回NULL。如果查找不到delim中的字符时,返回当前strtok的字符串的指针。所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。
第三种(字典树):
#include<iostream> #include<cstdio> #include<cstring> using namespace std; struct node { int cnt; struct node *next[26]; node() { cnt=0; memset(next,0,sizeof(next)); } }; node *root = NULL; int sum; void Createtrie(char *s) { node *p=root;//根节点 node *tmp=NULL;//不要忘了初始化指针 int len=strlen(s); for(int i=0;i<len;i++) { int t=s[i]-'a'; if(p->next[t]==NULL) { tmp=new node; p->next[t]=tmp; } p=p->next[t]; } if(!p->cnt) sum++; p->cnt++; } int main() { int len; char str[1000005],s[1005]; while(gets(str)) { if(strcmp(str,"#")==0) break; root = new node;//创建新节点 len=strlen(str); sum=0;//初始化 for(int i=0;i<len;i++) { while(str[i++]==' '); i--; if(i==len) break; int j=0; while(str[i]!=' '&&i<len) s[j++]=str[i++]; s[j]='\0';//加上结束标志 Createtrie(s); } cout<<sum<<endl; } }字典树
又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
第四种(map容器):
#include<iostream> #include<map> using namespace std; int main() { string n; map<string,int> m; while(getline(cin,n)&&n!="#") { string str; m.clear(); int len=n.length(); for(int i=0;i<len;i++) { if(isalpha(n[i])) { str.clear(); int j; for(j=i;isalpha(n[j])&&j<len;j++) str+=n[j]; i=j; m[str]++; } } cout<<m.size()<<endl; } }
#include<iostream> #include<set> #include<string> using namespace std; int main() { set<string> st; string str; char c; str.clear(); while((c=cin.get())!='#') { while(c!=' '&&c!='\n') { str+=c; c=cin.get(); } if(str.length()) { st.insert(str); str.clear(); } if(c=='\n') { cout<<st.size()<<endl; st.clear(); str.clear(); } } return 0; }