1.hdu 1305 Immediate Decodability
算法思路:trie树模板,在插入的同时进行统计是否存在,有想法,得动脑子,当脑子空洞的时候,注意要有逻辑判断能力,大胆想,大胆假设
现在假定两个字符串A,B。 A的长度小于B。分两种情况,
当B先输入时(即长的先输入),途经的结点的flag如果为1,即如果有小于B的单词,便为前缀。
当A先输入时(即短的先输入),当建立到A的最后一个字符时, 如果该结点已存在,那么证明,已有一个以该字符为前缀的字符已经输入。
#include<bits/stdc++.h> using namespace std; struct node{ int a[2];int end_; }trie[2000]; char s[15]; int tot=1;int res=1; void insert(char s[]) { int p=0;int len=strlen(s); for(int i=0;i<len;i++) { int t=s[i]-'0'; if(trie[p].a[t]==0) trie[p].a[t]=tot++; p=trie[p].a[t]; if(trie[p].end_==1) res=0; } trie[p].end_=1; } void init(){ for(int i=0;i<=2000;i++) { trie[i].a[0]=0,trie[i].a[1]=0,trie[i].end_=0; } tot=1;res=1; } int main() { int num=1; while(cin>>s) { init();insert(s); while(cin>>s){ if(s[0]=='9') break; else insert(s); } if(res==1) printf("Set %d is immediately decodable\n",num); else printf("Set %d is not immediately decodable\n",num); num++; } return 0; }
算法思路:trie树模板,走过一个节点,数量+1;
#include<bits/stdc++.h> using namespace std; struct node{ int a[26],num; }trie[10000000]; char s[10];int tot=1; void insert(char s[]) { int len=strlen(s);int p=0; for(int i=0;i<len;i++) { int t=s[i]-'a'; if(trie[p].a[t]==0) trie[p].a[t]=tot++; p=trie[p].a[t]; trie[p].num++; } } int find(char s[]) { int p=0;int len=strlen(s); for(int i=0;i<len;i++) { int t=s[i]-'a'; p=trie[p].a[t]; if(p==0) return 0; } return trie[p].num; } int main() { int tmp=1; while(cin.getline(s,20)) { if(strlen(s)==0) {tmp=0;continue;} if(tmp==1) insert(s); else { int ans=find(s); cout<<ans<<endl; } } return 0; }
算法思路:同1
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1e5+5; /*struct node{ int a[10],end; }trie[maxn];*/ int trie[maxn][10],cmp[maxn]; int res=1,tot=1;char s[20]; void insert(char s[],int k,int n) { int len=strlen(s);int p=0; for(int i=0;i<len;i++) { int t=s[i]-'0'; if(trie[p][t]==0) trie[p][t]=tot++; p=trie[p][t]; if(cmp[p]==1) res=0; } cmp[p]=1; /*if(k==n){ for(int i=0;i<=9;i++){ if(trie[p][i]!=0){ res=0; break; } } }*/ for(int i=0;i<10;i++) if(trie[p][i]!=0) res=0; } void init() { for(int i=0;i<maxn;i++) { for(int j=0;j<=9;j++) { trie[i][j]=0; } cmp[i]=0; } tot=1,res=1; } int main() { int t;cin>>t; while(t--) { init(); int n;cin>>n; for(int i=1;i<=n;i++) { cin>>s; if(res) insert(s,i,n); else continue; } if(res==1) printf("YES\n"); else printf("NO\n"); } return 0; }
4.hdu 1075 What Are You Talking About
算法思路:火星文替换,trie树模板,增加火星文的空间,如果是结尾时,则将火星文给他,另外这题的gets用法和字符串指针的用法很奇妙
gets会将换行符变为字符串结束符,对字符串的处理能力弱弱弱,另外注意%s时需用getchar吞掉换行符!!
#include<bits/stdc++.h> using namespace std; struct node{ int a[26];char chh[20];int end; }trie[1000000];int tot=1; void insert(char *ch1, char *ch2)//ch1 mars,ch2 e a { int p=0; for(int i=0;ch1[i]!='\0';i++) { int t=ch1[i]-'a'; if(trie[p].a[t]==0) trie[p].a[t]=tot++; p=trie[p].a[t]; } trie[p].end=1;strcpy(trie[p].chh,ch2); } void query(char *ch1) { int p=0; for(int i=0;ch1[i]!='\0';i++) { int t=ch1[i]-'a'; p=trie[p].a[t]; if(p==0) { printf("%s",ch1);return; } } if(trie[p].end) { printf("%s",trie[p].chh);return; } else {printf("%s",ch1);return;} } int main() { char ch1[3010],ch2[3010]; scanf("%s",&ch1); while(~scanf("%s",&ch2)) { if(strcmp(ch2,"END")!=0) { scanf("%s",&ch1); insert(ch1,ch2); } else break; } scanf("%s",&ch1);//cout<<ch1; getchar(); while(gets(ch1)!=NULL) { //cout<<ch1; if(strcmp(ch1,"END")==0){ break;} else { //cout<<"233"; int len=strlen(ch1);int tmp=0;char cc; ch1[len]='\n';ch1[len+1]='\0';//gets会将换行符变成字符串结束符 for(int i=0;i<=len;i++) { if(!islower(ch1[i])) { cc=ch1[i]; ch1[i]='\0';//标记为结尾 query(ch1+tmp); tmp=i+1; printf("%c",cc); } } } } return 0; }
算法思路:
一开始没有明白题意,看了好久,才明白,原来它是将一个单词打印出来后再在打印机里面删除字母,也就是说,如果单词前缀相同,则只需删除单词不相同的部分,再插入下一个单词不相同的部分。这样的话,可以用字典树,要是单词前缀相同,则在字典树上只有一个结点,那么,要是将最长的那个单词也删除了,则是对字典树上的结点插入一次再删除一次,还要输出n次,也就是2*numnode+n;但是最长的那个单词len不需要删除,则是2*numnode+n-len;
#include<bits/stdc++.h> using namespace std; struct node{ int a[26],end; }trie[500010]; void init(){ for(int i=0;i<500010;i++) { for(int j=0;j<26;j++) { trie[i].a[j]=0; } trie[i].end=0; } } int tot=1; void insert(char *s) { int p=0;int len=strlen(s); for(int i=0;i<len;i++) { int t=s[i]-'a'; if(trie[p].a[t]==0) trie[p].a[t]=tot++; p=trie[p].a[t]; } trie[p].end=1; } int main() { int n;char s[50]; while(cin>>n){ init();tot=1;int maxnum=0; for(int i=1;i<=n;i++) { scanf("%s",&s); insert(s); int tmp=strlen(s); maxnum=max(tmp,maxnum); } cout<<(tot-1)*2-maxnum+n<<endl; } return 0; }
算法思路:其实用字符串处理+trie或者set都可以,重点是字符串的处理。。。。。sscanf,gets的用法,指针不断移动
#include<bits/stdc++.h> using namespace std; set<string>aa;//set中第一次加上string int main()//语言无非就是字母数字符号了 { while(1) { char tmp[1000]; char s[10000];cin.getline(s,10000);//让我复习了getline的用法 int nums=strlen(s); if(s[0]=='#') break; int num=0; while(s[num]==' ') num++;//此法可以用来判断非字母的任何作为间隔的东西 while(num<nums)//字符串的分割 { sscanf(s+num,"%s",tmp); int len1=strlen(tmp); //cout<<len1<<' '<<tmp<<endl; aa.insert(tmp);//char到string的自动转换 num+=len1;//很不明白题目为什莫要挖这莫多坑 num++;//溜了溜了 while(s[num]==' ') num++;//消除间隔 ,防止错位 } cout<<aa.size()<<endl; aa.clear(); } return 0; }