hdu1251 hdu1247 hdu4099 字典树

梳理了一下字典序:

hdu1251裸 字典树

View Code
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 using namespace std;
 5 struct trie{
 6     int cnt;
 7     trie *next[26];
 8 };
 9 trie *root=new trie;
10 void insert(char s[]){
11     trie *p=root,*newnode;
12     for(int i=0;s[i]!='\0';i++){
13         if(p->next[s[i]-'a']!=NULL){
14             p=p->next[s[i]-'a'];
15             p->cnt++;
16         }else{
17             newnode=new trie;
18             for(int j=0;j!=26;j++)
19                 newnode->next[j]=NULL;
20             newnode->cnt=1;
21             p->next[s[i]-'a']=newnode;
22             p=newnode;
23         }
24     }
25 }
26 int find(char s[]){
27     trie *p=root;
28     for(int i=0;s[i]!='\0';i++){
29         if(p->next[s[i]-'a']!=NULL)
30             p=p->next[s[i]-'a'];
31         else
32             return 0;
33     }
34     return p->cnt;
35 }
36 int main(){
37     char s[20];
38     for(int i=0;i!=26;i++)
39         root->next[i]=NULL;
40     root->cnt=0;
41     while(gets(s)){
42         if(!strcmp(s,"")) break;
43         insert(s);
44     }
45     while(scanf("%s",s)!=EOF){
46         printf("%d\n",find(s));
47     }
48     return 0;
49 }
50 /*
51 Sample Input
52 banana
53 band
54 bee
55 absolute
56 acm
57 
58 ba
59 b
60 band
61 abc
62 Sample Output
63 2
64 3
65 1
66 0
67 */

hdu1247 字典树变形,题意:输入n个字符串,如果存在字符串a,b,c,满足c=a+b,输出c

将所有字符串建树或者map存储,然后遍历一遍,将每个字符串拆成两部分,分别查找看是否存在,存在输出该字符串~

map代码:280ms+

View Code
 1 #include<iostream>
 2 #include<string>
 3 #include<map>
 4 using namespace std;
 5 string str[50005];
 6 int main(){
 7     map<string,int>m;
 8     int cnt=0;
 9     while(cin>>str[cnt]){
10           m[str[cnt]]=1;
11           cnt++;
12     }
13     for(int i=0;i<cnt;i++){
14         for(int j=1;j!=str[i].length();j++){
15             string s1(str[i],0,j);
16             string s2(str[i],j);
17             if(m.find(s1)!=m.end() && m.find(s2)!=m.end()){
18             //if(m[s1]&&m[s2])
19             //If you use this sentence instead of the above will slow 100ms!!
20                  cout<<str[i]<<endl;
21                  break;//Don't forget£¡Otherwise WA!!
22             }
23         }
24     }
25     return 0;
26 }

字典树的代码,一开始写的很挫,map还280ms,字典树却250ms,后来参考了一下别人的,31ms~

View Code
 1 //字典树做法就是用字典树来代替map判断字符串是否在词典中存在。
 2 #include<iostream>
 3 #include<cstring>
 4 #include<stdio.h>
 5 using namespace std;
 6 struct Trie{
 7        void init(){
 8             memset(child,0,sizeof(child));
 9             end=false;
10        }
11        Trie *child[26];
12        bool end;//用来判断这个点是不是一个单词的最后一个点
13 }trie[50005];
14 int cnt;
15 char str[50005][21];
16 void insert(const char *source){
17      Trie *current=&trie[0]; //根节点
18      for(int i=0;source[i];i++){
19          if(current->child[source[i]-'a'])
20               current=current->child[source[i]-'a'];
21          else{
22               current->child[source[i]-'a']=&trie[++cnt];
23               trie[cnt].init();
24               current=current->child[source[i]-'a'];
25          }
26      }
27      current->end=true;
28 }
29 int find(const char *source){
30     Trie *current=&trie[0];
31     for(int i=0;source[i];i++){
32         if(current->child[source[i]-'a'])
33              current=current->child[source[i]-'a'];
34         else
35              return 0;
36     }
37     if(current->end)
38         return 1;
39     else
40         return 0;
41 }
42 int main(){
43     int str_cnt=0;
44     cnt=0;
45     trie[0].init();
46     while(scanf("%s",str[str_cnt])==1){
47          insert(str[str_cnt]);
48          str_cnt++;
49     }
50     int f;
51     char ch;
52     for(int i=0;i<str_cnt;i++){
53         for(int j=1;j!=strlen(str[i]);j++){
54             int f=0;
55             ch=str[i][j];
56             str[i][j]='\0';
57             if(find(str[i])) //传递指针,加快速度
58                 f++;
59             str[i][j]=ch;
60             if(find(str[i]+j))
61                 f++;
62             if(f==2){
63                 puts(str[i]);
64                 break;
65             }
66         }
67     }
68     return 0;
69 }

hdu4099 暴力计算0~10 0000 的Fibonacci前60位(插入字典树只需插入前40位),建树,没输入一个字符串查询~

代码写的很挫很挫很挫很挫~~用java大数打好数据,调试了好几个小时~~还好1A了~~

View Code
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 using namespace std;
  5 #define M 100000
  6 char f[M+5][70]={"1","1",};
  7 //add函数,大数模板,计算斐波那契数
  8 void add(char *a,char *b,char *c){
  9     int i;
 10     int c1[105];
 11     memset(c1,0,sizeof(c1));
 12     int l1=strlen(a);
 13     int l2=strlen(b);
 14     int top=0;
 15     for(i=1;i<=l1&&i<=l2;i++)
 16         c1[top++]=a[l1-i]+b[l2-i]-'0'*2;
 17     while(i<=l1){
 18         c1[top++]=a[l1-i]-'0';
 19         i++;
 20     }
 21     while(i<=l2){
 22         c1[top++]=b[l2-i]-'0';
 23         i++;
 24     }
 25     int t=0;
 26     for(i=0;i<top+3;i++){
 27         c1[i+1]+=(c1[i]+t)/10;
 28         c1[i]=(c1[i]+t)%10;
 29     }
 30     int begin=0,flag=0;
 31     int end=top+3;
 32     for(i=end;i>=0;i--){
 33         if(c1[i]!=0||flag){
 34             flag=1;
 35             c[begin++]=c1[i]+'0';
 36         }
 37     }
 38     c[begin]='\0';
 39     return ;
 40 }
 41 struct trie{
 42     int cnt;//标记位置
 43     trie *next[10];
 44 };
 45 //建树
 46 trie *root=new trie;
 47 void insert(char *ch,int index){
 48     trie *p=root,*newnode;
 49     int len=strlen(ch);
 50     for(int i=0;i<len;i++){
 51         if(p->next[ch[i]-'0']==NULL){
 52             newnode=new trie;
 53             for(int j=0;j!=10;j++){
 54                 newnode->next[j]=NULL;
 55             }
 56             p->next[ch[i]-'0']=newnode;
 57             p=newnode;
 58             p->cnt=index;
 59         }else{
 60             p=p->next[ch[i]-'0'];
 61             if(p->cnt==-1){
 62                 p->cnt=index;
 63             }
 64         }
 65     }
 66     return ;
 67 }
 68 //查找函数
 69 int find(char *ch){
 70     trie *p=root;
 71     for(int i=0;ch[i]!='\0';i++){
 72         if(p->next[ch[i]-'0']!=NULL)
 73             p=p->next[ch[i]-'0'];
 74         else
 75             return -1;
 76     }
 77     return p->cnt;
 78 }
 79 int main(){
 80     char ch[50];
 81     for(int i=0;i!=10;i++){
 82         root->next[i]=NULL;
 83     }
 84     root->cnt=-1;
 85 
 86     ch[0]='1';
 87     ch[1]='\0';
 88     insert(ch,0);
 89 
 90     for(int i=2;i<M;i++){
 91         add(f[i-1],f[i-2],f[i]);
 92         int f_len=strlen(f[i]);
 93 
 94         int f_end=min(f_len,40);
 95         for(int j=0;j<f_end;j++){
 96             ch[j]=f[i][j];
 97         }
 98         ch[f_end]='\0';
 99 
100         insert(ch,i);
101 
102         if(f_len>60){//如果大于60位,就减少一位
103             f[i][60]='\0';
104             int f1_len=strlen(f[i-1]);
105             f[i-1][f1_len-(f_len-60)]='\0';
106         }
107     }
108     int T=0,t;
109     scanf("%d",&t);
110     while(t--){
111         scanf("%s",ch);
112         printf("Case #%d: %d\n",++T,find(ch));
113     }
114     return 0;
115 }

以上这个搓搓的代码在自己学校OJ上就MLE了,下面这个可以AC~

二分法。大概思路:先将一个数组串数组in将输入的所有测试数据存起来,sort一下,然后开始计算Fibonacci数列,

每计算一次,就用二分查找看in数组里有没有对应项,然后将i存入到in数组对应的结构体中,都计算结束之后,再sort回来原来的序列,

输出答案。代码还没有写,这是别人的,稍后补上:

View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<string.h>
  4 #include<algorithm>
  5 using namespace std;
  6 #define  mm  69  //保存的fib数列的位数(长度) 或59 或79 都ok
  7 struct IN  // 存输入的数据
  8 {
  9     char ss[44];
 10     int ans,id;
 11 }in[50008];
 12 struct AA   // 存 fib 数列
 13 {
 14     int x[mm],len;
 15 }one[100005];
 16 char ss[50],ST[50];
 17 
 18 
 19 int bySS(IN x,IN y)  // 按ss值的大小排序(这里是从小到大)
 20 {
 21     return strcmp(x.ss,y.ss) < 0;
 22 }
 23 int byID(IN x,IN y) // 按id值的大小排序(这里是从小到大)
 24 {
 25     return x.id < y.id;
 26 }
 27 
 28 int main()
 29 {
 30 //    freopen("indata.txt","r",stdin);
 31  //   freopen("out.txt","w",stdout);
 32     int i,j,k,test,len;
 33     int le,ri,mid,fg;
 34     scanf("%d",&test);
 35     for(getchar(),i=0;i < test;i++)
 36     {
 37         gets(in[i].ss);
 38         in[i].ans = -1;
 39         in[i].id = i;
 40     }
 41     sort(in,in+test,bySS);
 42     memset(one,0,sizeof(one));
 43     one[0].x[1] = one[1].x[1] = one[0].len = one[1].len = 1;
 44     for(i=0;i < test;i++)   //如果字符串是"1",则其ans直接就是0
 45         if(strcmp(in[i].ss,"1") == 0 && in[i].ans == -1)
 46             in[i].ans = 0;
 47     for(i=2;i < 100000;i++) //循环,同时处理要求的数据
 48     {
 49         for(j=1;j <= mm-9;j++) // fib 的计算
 50             one[i].x[j] = one[i-1].x[j] + one[i-2].x[j];
 51         for(j=1;j <= mm-9;j++) // 进位处理
 52             if(one[i].x[j] > 9)
 53                 one[i].x[j+1]++, one[i].x[j]%=10;
 54         for(j=mm-4;;j--)
 55             if(one[i].x[j])
 56                 break; //找到第一个非0位
 57         one[i].len = j;  //保存长度
 58         for(len=0;len<=40 && j >= 1;j--,len++)
 59             ss[len] = one[i].x[j]+'0'; //保存最多前40位
 60         ss[len] = '\0';
 61         memset(ST,'\0',sizeof(ST));
 62         for(k=0;k < len;k++) //从一位到最多40位,依次去找,并且处理要求的数据
 63         {
 64             ST[k] = ss[k];
 65             fg=le=0, ri=test-1;
 66             while(le <= ri) //二分查找
 67             {
 68                 mid = (le+ri)/2;
 69                 if(strcmp(ST,in[mid].ss) == 0)
 70                 {
 71                     fg=1;
 72                     break;
 73                 }
 74                 else if(strcmp(in[mid].ss,ST) < 0)
 75                     le = mid+1;
 76                 else
 77                     ri = mid-1;
 78             }
 79             if(fg)  // 查找成功,并对应处理。
 80             {
 81                 for(j=mid;j >= 0;j--)
 82                     if(strcmp(in[j].ss,in[mid].ss) == 0 && in[j].ans == -1)
 83                         in[j].ans = i;
 84                     else
 85                         break;
 86                 for(j=mid+1;j < test;j++)
 87                     if(strcmp(in[j].ss,in[mid].ss) == 0 && in[j].ans == -1)
 88                         in[j].ans = i;
 89                     else
 90                         break;
 91             }
 92         }
 93     //        printf("i=%d ss=%s\n",i,ss);
 94         if(one[i].len == mm-8)//表示多出了一位,则需要把整个字符串向后移动一位。
 95         {
 96             for(j=1;j <= mm-9;j++) //向后移动一位
 97                 one[i].x[j] = one[i].x[j+1];
 98             one[i].x[mm-8] = 0; //最前面的那位要置0
 99             for(j=1;j < one[i-1].len;j++) //同理处理之。
100                 one[i-1].x[j] = one[i-1].x[j+1];
101             one[i-1].x[one[i-1].len] = 0;
102             one[i-1].len--;  //长度减一
103             one[i].len--;
104         }
105     }
106     sort(in,in+test,byID); //按id值排序,
107     for(i=0;i < test;i++) //输出结果。
108         printf("Case #%d: %d\n",i+1,in[i].ans);
109     return 0;
110 }


 

posted @ 2013-01-13 00:50  _sunshine  阅读(364)  评论(0编辑  收藏  举报