zoukankan      html  css  js  c++  java
  • 并查集-字典树

    并查集优化方式:
    1.按秩合并;
    2.路径压缩;
    按秩合并里的秩指的是一个父亲下属的节点数,也就是它的最大深度.
    根据算法导论这两个优化只使用一个时间复杂度是nlogn级别,但同时使用时间复杂度将降为超线性O(mα(n)).α(n)是阿克曼函数的逆函数.
    做了几道题,合并在这里:

    小希的迷宫

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 18763    Accepted Submission(s): 5709


    Problem Description
    上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走。但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双向连通的,就是说如果有一个通道连通了房间A和B,那么既可以通过它从房间A走到房间B,也可以通过它从房间B走到房间A,为了提高难度,小希希望任意两个房间有且仅有一条路径可以相通(除非走了回头路)。小希现在把她的设计图给你,让你帮忙判断她的设计图是否符合她的设计思路。比如下面的例子,前两个是符合条件的,但是最后一个却有两种方法从5到达8。

     

    Input
    输入包含多组数据,每组数据是一个以0 0结尾的整数对列表,表示了一条通道连接的两个房间的编号。房间的编号至少为1,且不超过100000。每两组数据之间有一个空行。
    整个文件以两个-1结尾。
     

    Output
    对于输入的每一组数据,输出仅包括一行。如果该迷宫符合小希的思路,那么输出"Yes",否则输出"No"。
     

    Sample Input
    6 8  5 3  5 2  6 4
    5 6  0 0

    8 1  7 3  6 2  8 9  7 5
    7 4  7 8  7 6  0 0

    3 8  6 8  6 4
    5 3  5 6  5 2  0 0

    -1 -1
     

    Sample Output
    Yes
    Yes
    No
     

    Author
    Gardon
     

    Source
    HDU 2006-4 Programming Contest
     

    Recommend
    lxj

     

    #include<stdio.h>
    int father[100025];
    bool sign[100025];
    bool flag;
    int getfather(int v)
    {
        if (father[v]==v) return father[v];
        father[v]=getfather(father[v]);
        return father[v];
    }
    void merge(int u,int v)
    {
        int x=getfather(u);
        int y=getfather(v);
        if (x==y) flag=false;
        else father[x]=y;
    }
    int main()
    {
        int u,v;
        while (scanf("%d%d",&u,&v)!=EOF)
        {
            int i;
            if (u+v==-2) return 0;
            if (u+v==0)
            {
                printf("Yes
    ");
                continue;
            }
            flag=true;
            for (i=1;i<=100000;i++)
            {
                father[i]=i;
                sign[i]=false;
            }
            sign[u]=sign[v]=1;
            merge(u,v);
            while (scanf("%d%d",&u,&v)!=EOF)
            {
                if (u+v==0) break;
                if (flag) merge(u,v);
                sign[u]=sign[v]=true;
            }
            bool tot=0;
            for (i=1;i<=100000;i++)
                if (sign[i] && father[i]==i) tot++;
            if (tot!=1) flag=false;
            if (flag) printf("Yes
    ");
            else printf("No
    ");
        }
    }
    View Code

    More is better

    Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 327680/102400 K (Java/Others)
    Total Submission(s): 9587    Accepted Submission(s): 3528


    Problem Description
    Mr Wang wants some boys to help him with a project. Because the project is rather complex, the more boys come, the better it will be. Of course there are certain requirements.

    Mr Wang selected a room big enough to hold the boys. The boy who are not been chosen has to leave the room immediately. There are 10000000 boys in the room numbered from 1 to 10000000 at the very beginning. After Mr Wang's selection any two of them who are still in this room should be friends (direct or indirect), or there is only one boy left. Given all the direct friend-pairs, you should decide the best way.
     

    Input
    The first line of the input contains an integer n (0 ≤ n ≤ 100 000) - the number of direct friend-pairs. The following n lines each contains a pair of numbers A and B separated by a single space that suggests A and B are direct friends. (A ≠ B, 1 ≤ A, B ≤ 10000000)
     

    Output
    The output in one line contains exactly one integer equals to the maximum number of boys Mr Wang may keep.
     

    Sample Input
    4
    1 2
    3 4
    5 6
    1 6
    4
    1 2
    3 4
    5 6
    7 8
     

    Sample Output
    4
    2

    Hint

    A and B are friends(direct or indirect), B and C are friends(direct or indirect),
    then A and C are also friends(indirect).

     In the first sample {1,2,5,6} is the result.
    In the second sample {1,2},{3,4},{5,6},{7,8} are four kinds of answers.
     
     
     

    Author
    lxlcrystal@TJU
     

    Source
    HDU 2007 Programming Contest - Final
     

    Recommend
    lcy

    #include<stdio.h>
    int Max;
    int father[10000025],rank[10000025];
    int getfather(int v)
    {
        if (father[v]==v) return v;
        father[v]=getfather(father[v]);
        return father[v];
    }
    void merge(int u,int v)
    {
         int x=getfather(u);
         int y=getfather(v);
         if (x!=y)
         {
             father[x]=y;
             rank[y]+=rank[x];
             if (rank[y]>Max) Max=rank[y];
         }
    }
    int main()
    {
        int n;
        while (scanf("%d",&n)!=EOF)
        {
            int i;
            for (i=1;i<=10000000;i++)
            {
                father[i]=i;
                rank[i]=1;
            }
            Max=1;
            for (i=1;i<=n;i++)
            {
                int u,int v;
                scanf("%d%d",&u,&v);
                merge(u,v);
            }
            printf("%d
    ",Max);
        }
        return 0;
    }
    View Code

    Virtual Friends

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2563    Accepted Submission(s): 725


    Problem Description
    These days, you can do all sorts of things online. For example, you can use various websites to make virtual friends. For some people, growing their social network (their friends, their friends' friends, their friends' friends' friends, and so on), has become an addictive hobby. Just as some people collect stamps, other people collect virtual friends.

    Your task is to observe the interactions on such a website and keep track of the size of each person's network.

    Assume that every friendship is mutual. If Fred is Barney's friend, then Barney is also Fred's friend.
     

    Input
    Input file contains multiple test cases.
    The first line of each case indicates the number of test friendship nest.
    each friendship nest begins with a line containing an integer F, the number of friendships formed in this frindship nest, which is no more than 100 000. Each of the following F lines contains the names of two people who have just become friends, separated by a space. A name is a string of 1 to 20 letters (uppercase or lowercase).
     

    Output
    Whenever a friendship is formed, print a line containing one integer, the number of people in the social network of the two people who have just become friends.
     

    Sample Input
    1
    3
    Fred Barney
    Barney Betty
    Betty Wilma
     

    Sample Output
    2
    3
    4
     

    Source
    University of Waterloo Local Contest 2008.09
     

    Recommend
    chenrui

     

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    struct A
    {
        int pre;
        int total;
    } E[100025];
    int k;
    struct dictree
    {
        struct dictree *child[52];
        int flag;
    };
    struct dictree *root;
    void insert(char *str)
    {
        struct dictree *now,*next;
        int i,j,len,tmp;
        now=root;
        len=strlen(str);
        for (i=0;i<len;i++)
        {
            tmp=str[i]-'A';
            if (now->child[tmp]) now=now->child[tmp];
            else
            {
                next=(struct dictree *)malloc(sizeof(struct dictree));
                for (j=0;j<52;j++) next->child[j]=0;
                next->flag=0;
                now->child[tmp]=next;
                now=next;
            }
        }
        now->flag=k;
        E[k].pre=k;
        E[k].total=1;
        k++;
    }
    int f_tree(char *str)
    {
        struct dictree *next;
        int i,len,tmp;
        len=strlen(str);
        next=root;
        for (i=0;i<len;i++)
        {
            tmp=str[i]-'A';
            if (next->child[tmp]) next=next->child[tmp];
            else return 0;
        }
        return next->flag;
    }
    int f_u(int k)
    {
        if (E[k].pre==k) return k;
        E[k].pre=f_u(E[k].pre);
        return E[k].pre;
    }
    void Union(int f1,int f2)
    {
        E[f1].pre=f2;
        E[f2].total+=E[f1].total;
    }
    int main()
    {
        int T,n,i,f1,f2,a,b;
        char str1[25],str2[25];
        while (scanf("%d",&T)!=EOF)
        {
            while (T--)
            {
                scanf("%d",&n);
                root=(struct dictree *)malloc(sizeof(dictree));
                for (i=0;i<52;i++) root->child[i]=0;
                root->flag=0;
                k=1;
                while (n--)
                {
                    scanf("%s%s",&str1,&str2);
                    for (i=0;str1[i];i++) if (str1[i]>='a') str1[i]-=6;
                    for (i=0;str2[i];i++) if (str2[i]>='a') str2[i]-=6;
                    a=f_tree(str1);
                    b=f_tree(str2);
                    if (a==0) {a=k;insert(str1);}
                    if (b==0) {b=k;insert(str2);}
                    f1=f_u(a);
                    f2=f_u(b);
                    if (f1!=f2) Union(f1,f2);
                    printf("%d
    ",E[f2].total);
                }
            }
        }
        return 0;
    }
    View Code

     

    Farm Irrigation

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 3940    Accepted Submission(s): 1724


    Problem Description
    Benny has a spacious farm land to irrigate. The farm land is a rectangle, and is divided into a lot of samll squares. Water pipes are placed in these squares. Different square has a different type of pipe. There are 11 types of pipes, which is marked from A to K, as Figure 1 shows.

     

    Figure 1


    Benny has a map of his farm, which is an array of marks denoting the distribution of water pipes over the whole farm. For example, if he has a map

    ADC
    FJK
    IHE

    then the water pipes are distributed like

     

    Figure 2


    Several wellsprings are found in the center of some squares, so water can flow along the pipes from one square to another. If water flow crosses one square, the whole farm land in this square is irrigated and will have a good harvest in autumn.

    Now Benny wants to know at least how many wellsprings should be found to have the whole farm land irrigated. Can you help him?

    Note: In the above example, at least 3 wellsprings are needed, as those red points in Figure 2 show.
     

    Input
    There are several test cases! In each test case, the first line contains 2 integers M and N, then M lines follow. In each of these lines, there are N characters, in the range of 'A' to 'K', denoting the type of water pipe over the corresponding square. A negative M or N denotes the end of input, else you can assume 1 <= M, N <= 50.
     

    Output
    For each test case, output in one line the least number of wellsprings needed.
     

    Sample Input
    2 2
    DK
    HF

    3 3
    ADC
    FJK
    IHE

    -1 -1
     

    Sample Output
    2
    3
     

    Author
    ZHENG, Lu
     

    Source
    Zhejiang University Local Contest 2005
     

    Recommend
    Ignatius.L

    #include<stdio.h>
    #include<string.h>
    char s[60][60];
    int f[3000][5],father[3000];
    int getfather(int v)
    {
        if (father[v]==v) return v;
        father[v]=getfather(father[v]);
        return father[v];
    }
    void merge(int u,int v)
    {
        int x=getfather(u);
        int y=getfather(v);
        father[x]=y;
    }
    int main()
    {
        int n,m;
        while (scanf("%d%d",&n,&m)!=EOF)
        {
            if (n+m==-2) return 0;
            int i,j;
            for (i=1;i<=n;i++) scanf("%s",s[i]);
            for (i=1;i<=n;i++)
                for (j=m;j>=1;j--)
                    s[i][j]=s[i][j-1];
            memset(f,0,sizeof(f));
            for (i=1;i<=n;i++)
                for (j=1;j<=m;j++)
                {
                    if (s[i][j]=='A')
                    {
                        f[(i-1)*m+j][1]=true;
                        f[(i-1)*m+j][4]=true;
                    }
                    if (s[i][j]=='B')
                    {
                        f[(i-1)*m+j][1]=true;
                        f[(i-1)*m+j][2]=true;
                    }
                    if (s[i][j]=='C')
                    {
                        f[(i-1)*m+j][3]=true;
                        f[(i-1)*m+j][4]=true;
                    }
                    if (s[i][j]=='D')
                    {
                        f[(i-1)*m+j][2]=true;
                        f[(i-1)*m+j][3]=true;
                    }
                    if (s[i][j]=='E')
                    {
                        f[(i-1)*m+j][1]=true;
                        f[(i-1)*m+j][3]=true;
                    }
                    if (s[i][j]=='F')
                    {
                        f[(i-1)*m+j][2]=true;
                        f[(i-1)*m+j][4]=true;
                    }
                    if (s[i][j]=='G')
                    {
                        f[(i-1)*m+j][1]=true;
                        f[(i-1)*m+j][2]=true;
                        f[(i-1)*m+j][4]=true;
                    }
                    if (s[i][j]=='H')
                    {
                        f[(i-1)*m+j][1]=true;
                        f[(i-1)*m+j][3]=true;
                        f[(i-1)*m+j][4]=true;
                    }
                    if (s[i][j]=='I')
                    {
                        f[(i-1)*m+j][2]=true;
                        f[(i-1)*m+j][3]=true;
                        f[(i-1)*m+j][4]=true;
                    }
                    if (s[i][j]=='J')
                    {
                        f[(i-1)*m+j][1]=true;
                        f[(i-1)*m+j][2]=true;
                        f[(i-1)*m+j][3]=true;
                    }
                    if (s[i][j]=='K')
                    {
                        f[(i-1)*m+j][1]=true;
                        f[(i-1)*m+j][2]=true;
                        f[(i-1)*m+j][3]=true;
                        f[(i-1)*m+j][4]=true;
                    }
                }
            for (i=1;i<=n*m;i++) father[i]=i;
            for (i=1;i<=n;i++)
                for (j=1;j<=m;j++)
                {
                    int u=(i-1)*m+j;
                    if (u>m && f[u][1] && f[u-m][3]) merge(u,u-m);
                    if (j<m && f[u][2] && f[u+1][4]) merge(u,u+1);
                }
            int tot=0;
            for (i=1;i<=n*m;i++)
                if (father[i]==i) tot++;
            printf("%d
    ",tot);
        }
        return 0;
    }
    View Code

    How Many Tables

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 9025    Accepted Submission(s): 4407


    Problem Description
    Today is Ignatius' birthday. He invites a lot of friends. Now it's dinner time. Ignatius wants to know how many tables he needs at least. You have to notice that not all the friends know each other, and all the friends do not want to stay with strangers.

    One important rule for this problem is that if I tell you A knows B, and B knows C, that means A, B, C know each other, so they can stay in one table.

    For example: If I tell you A knows B, B knows C, and D knows E, so A, B, C can stay in one table, and D, E have to stay in the other one. So Ignatius needs 2 tables at least.
     

    Input
    The input starts with an integer T(1<=T<=25) which indicate the number of test cases. Then T test cases follow. Each test case starts with two integers N and M(1<=N,M<=1000). N indicates the number of friends, the friends are marked from 1 to N. Then M lines follow. Each line consists of two integers A and B(A!=B), that means friend A and friend B know each other. There will be a blank line between two cases.
     

    Output
    For each test case, just output how many tables Ignatius needs at least. Do NOT print any blanks.
     

    Sample Input
    2
    5 3
    1 2
    2 3
    4 5

    5 1
    2 5
     

    Sample Output
    2
    4
     

    Author
    Ignatius.L
     

    Source
    杭电ACM省赛集训队选拔赛之热身赛
     

    Recommend
    Eddy

    #include<stdio.h>
    #include<string.h>
    int f[1024][1024],father[1024];
    int getfather(int v)
    {
        if (father[v]==v) return v;
        father[v]=getfather(father[v]);
        return father[v];
    }
    void merge(int u,int v)
    {
         int x=getfather(u);
         int y=getfather(v);
         father[x]=y;
    }
    bool judge(int u,int v)
    {
         int x=getfather(u);
         int y=getfather(v);
         if (x==y) return true;
         else return false;
    }
    int main()
    {
        int n,m,T;
        scanf("%d",&T);
        
        while (T--)
        {
              scanf("%d%d",&n,&m);
              memset(f,0,sizeof(f));
              int ans=n;
              for (int i=1;i<=n;i++) father[i]=i;
              for (int i=1;i<=m;i++)
              {
                  int u,v;
                  scanf("%d%d",&u,&v);
                  if (f[u][v]) continue;
                  f[u][v]=1;
                  f[v][u]=1;
                  if (judge(u,v)) continue;
                  merge(u,v);
                  ans--;
              }
              printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    畅通工程

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 21937    Accepted Submission(s): 11413


    Problem Description
    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
     

    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
    注意:两个城市之间可以有多条道路相通,也就是说
    3 3
    1 2
    1 2
    2 1
    这种输入也是合法的
    当N为0时,输入结束,该用例不被处理。
     

    Output
    对每个测试用例,在1行里输出最少还需要建设的道路数目。
     

    Sample Input
    4 2
    1 3
    4 3
    3 3
    1 2
    1 3
    2 3
    5 2
    1 2
    3 5
    999 0
    0
     

    Sample Output
    1
    0
    2
    998

    Hint
    Hint
     
    Huge input, scanf is recommended.
     

    Source
    浙大计算机研究生复试上机考试-2005年
     

    Recommend
    JGShining

    #include<stdio.h>
    #include<string.h>
    int f[1024][1024],father[1024];
    int getfather(int v)
    {
        if (father[v]==v) return v;
        father[v]=getfather(father[v]);
        return father[v];
    }
    void merge(int u,int v)
    {
         int x=getfather(u);
         int y=getfather(v);
         father[x]=y;
    }
    bool judge(int u,int v)
    {
         int x=getfather(u);
         int y=getfather(v);
         if (x==y) return true;
         else return false;
    }
    int main()
    {
        int n,m;
        while (scanf("%d",&n)!=EOF)
        {
              if (n==0) return 0;
              scanf("%d",&m);
              memset(f,0,sizeof(f));
              int ans=n-1;
              for (int i=1;i<=n;i++) father[i]=i;
              for (int i=1;i<=m;i++)
              {
                  int u,v;
                  scanf("%d%d",&u,&v);
                  if (f[u][v]) continue;
                  f[u][v]=1;
                  f[v][u]=1;
                  if (judge(u,v)) continue;
                  merge(u,v);
                  ans--;
              }
              printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

     


    做HDU3172时结合了字典树,于是也做了几道题如下:

    What Are You Talking About

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/204800 K (Java/Others)
    Total Submission(s): 9702    Accepted Submission(s): 3061


    Problem Description
    Ignatius is so lucky that he met a Martian yesterday. But he didn't know the language the Martians use. The Martian gives him a history book of Mars and a dictionary when it leaves. Now Ignatius want to translate the history book into English. Can you help him?
     

    Input
    The problem has only one test case, the test case consists of two parts, the dictionary part and the book part. The dictionary part starts with a single line contains a string "START", this string should be ignored, then some lines follow, each line contains two strings, the first one is a word in English, the second one is the corresponding word in Martian's language. A line with a single string "END" indicates the end of the directory part, and this string should be ignored. The book part starts with a single line contains a string "START", this string should be ignored, then an article written in Martian's language. You should translate the article into English with the dictionary. If you find the word in the dictionary you should translate it and write the new word into your translation, if you can't find the word in the dictionary you do not have to translate it, and just copy the old word to your translation. Space(' '), tab(' '), enter(' ') and all the punctuation should not be translated. A line with a single string "END" indicates the end of the book part, and that's also the end of the input. All the words are in the lowercase, and each word will contain at most 10 characters, and each line will contain at most 3000 characters.
     

    Output
    In this problem, you have to output the translation of the history book.
     

    Sample Input
    START
    from fiwo
    hello difh
    mars riwosf
    earth fnnvk
    like fiiwj
    END
    START
    difh, i'm fiwo riwosf.
    i fiiwj fnnvk!
    END
     

    Sample Output
    hello, i'm from mars.
    i like earth!

    Hint

    Huge input, scanf is recommended.
     
     

    Author
    Ignatius.L

    自己做的不知错哪里了,粘上大牛的代码:
    #include"stdio.h"
    #include"ctype.h"
    #include"string.h"
    #include"stdlib.h"
    
    
    struct dictree
    {
        struct dictree *child[26];
        char aim[15];
        int flag;
    };
    struct dictree *root;
    
    
    void insert(char *source,char *temp)
    {
        int i,j;
        int len;
        struct dictree *current,*newnode;
    
    
        len=strlen(source);
        current=root;
        for(i=0;i<len;i++)
        {
            if(current->child[source[i]-'a']!=0)
                current=current->child[source[i]-'a'];
            else
            {
                newnode=(struct dictree *)malloc(sizeof(struct dictree));
                for(j=0;j<26;j++)    newnode->child[j]=0;
                newnode->flag=0;
                current->child[source[i]-'a']=newnode;
                current=newnode;
            }
        }
    
    
        current->flag=1;
        strcpy(current->aim,temp);
    }
    
    
    int flag;
    char ans[15];
    void find(char *source)
    {
        struct dictree *current;
        int i;
        int len;
    
    
        len=strlen(source);
        current=root;
    
    
        for(i=0;i<len;i++)
        {
            if(current->child[source[i]-'a']!=0)
                current=current->child[source[i]-'a'];
            else    {flag=1;return ;}
        }
        if(current->flag==0)    {flag=1;return;}
    
    
        strcpy(ans,current->aim);
    }
    
    
    int main()
    {
        char str1[15],str2[15];
        char str[3033];
        int i,j;
    
    
        int len;
        char temp[15];
    
        root=(struct dictree *)malloc(sizeof(struct dictree));
        for(j=0;j<26;j++)    root->child[j]=0;
        root->flag=0;
    
        scanf("%s",str1);
        while(scanf("%s",str1),strcmp(str1,"END")!=0)
        {
            scanf("%s",str2);
            insert(str2,str1);
        }
    
        scanf("%s",str);
        getchar();
        while(gets(str),strcmp(str,"END")!=0)
        {
            /*****/
            len=strlen(str);
            j=0;
            for(i=0;i<len;i++)
            {
                if(islower(str[i]))    temp[j++]=str[i];
                else
                {
                    if(j)
                    {
                        temp[j]=0;
                        flag=0;
                        find(temp);
                        if(flag)    printf("%s",temp);
                        else        printf("%s",ans);
                    }
                    if(str[i])        printf("%c",str[i]);
                    j=0;
                }
            }
            /*****/
            printf("
    ");
        }
        return 0;
    }
    View Code

     

    Hat’s Words

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 5426    Accepted Submission(s): 2024


    Problem Description
    A hat’s word is a word in the dictionary that is the concatenation of exactly two other words in the dictionary.
    You are to find all the hat’s words in a dictionary.
     

    Input
    Standard input consists of a number of lowercase words, one per line, in alphabetical order. There will be no more than 50,000 words.
    Only one case.
     

    Output
    Your output should contain all the hat’s words, one per line, in alphabetical order.
     

    Sample Input
    a
    ahat
    hat
    hatword
    hziee
    word
     

    Sample Output
    ahat
    hatword
     

    Author
    戴帽子的
     

    Recommend
    Ignatius.L

    #include<stdio.h>
    #include<string.h>
    class tnode
    {
    public:
        bool flag;
        tnode *child[26];
        tnode ()
        {
            flag=false;
            memset(child,0,sizeof(child));
        }
    };
    tnode *root;
    char s[50025][125];
    void insert(char *str)
    {
        tnode *now=root;
        int i,j,len=strlen(str),tmp;
        for (i=0;i<len;i++)
        {
            tmp=str[i]-'a';
            if (now->child[tmp]) now=now->child[tmp];
            else
            {
                now->child[tmp]=new tnode;
                now=now->child[tmp];
            }
        }
        now->flag=true;
    }
    void copy(int l,int r,char *src,char *tar)
    {
        int i;
        if (l>r) return;
        for (i=0;i<r-l+1+1;i++) tar[i]=src[i+l];
        tar[r-l+1]='';
    }
    bool find(char *str)
    {
        tnode *next=root;
        int i,len=strlen(str),tmp;
        for (i=0;i<len;i++)
        {
            tmp=str[i]-'a';
            if (next->child[tmp]) next=next->child[tmp];
            else return false;
        }
        return next->flag;
    }
    int main()
    {
        int i,j,n=1;
        char str1[125],str2[125];
        root=new tnode;
        freopen("input.txt","r",stdin);
        while (scanf("%s",s[n])!=EOF)
        {
            insert(s[n]);
            n++;
        }
        n--;
        for (i=1;i<=n;i++)
        {
            int len=strlen(s[i]);
            for (j=0;j<len-1;j++)
            {
                memset(str1,0,sizeof(str1));
                copy(0,j,s[i],str1);
                memset(str2,0,sizeof(str2));
                copy(j+1,len-1,s[i],str2);
                if (find(str1) && find(str2)) printf("%s
    ",s[i]);
            }
        }
        return 0;
    }
    View Code

    统计难题

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)
    Total Submission(s): 13090    Accepted Submission(s): 5540


    Problem Description
    Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
     

    Input
    输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.

    注意:本题只有一组测试数据,处理到文件结束.
     

    Output
    对于每个提问,给出以该字符串为前缀的单词的数量.
     

    Sample Input
    banana
    band
    bee
    absolute
    acm

    ba
    b
    band
    abc
     

    Sample Output
    2
    3
    1
    0
     

    Author
    Ignatius.L
     

    Recommend
    Ignatius.L
     

    #include<stdio.h>
    #include<string.h>
    class tnode
    {
    public:
        int num;
        tnode *child[26];
        tnode ()
        {
            num=0;
            memset(child,0,sizeof(child));
        }
    };
    tnode *root;
    void insert(char *str)
    {
        tnode *now=root;
        int i,len=strlen(str),tmp;
        for (i=0;i<len;i++)
        {
            tmp=str[i]-'a';
            if (now->child[tmp]==NULL) now->child[tmp]=new tnode;
            now=now->child[tmp];
            now->num++;
        }
    }
    int find(char *str)
    {
        tnode *now=root;
        int i,len=strlen(str),tmp;
        for (i=0;i<len;i++)
        {
            tmp=str[i]-'a';
            if (now->child[tmp]==NULL) return 0;
            now=now->child[tmp];
        }
        return now->num;
    }
    int main()
    {
        char temp[15];
        root=new tnode;
        while(gets(temp),strcmp(temp,"")!=0) insert(temp);  
        while(gets(temp)!=0)   printf("%d
    ",find(temp));  
        return 0;
    }
    View Code

     

  • 相关阅读:
    python基础五——初识函数
    python基础三——基础数据类型
    Python基础二
    python基础一
    2.配置jenkins
    1.jenkins 安装
    Java8 新特性
    Java8 新特性
    1.什么是 Docker
    idea快捷键
  • 原文地址:https://www.cnblogs.com/dramstadt/p/3188867.html
Copyright © 2011-2022 走看看