• How many


    题目大意:有 N 个手链,每个手链的最大长度不超过100,求出来最多有多少个不同的手链。
     
    分析:因为手链是可以转动的,所以只要两个手链通过转动达到相同,那么也被认为是一种手链,然而如果每次都循环比较的话无疑是非常浪费时间的,不过如果把每个串都用最小的字典序表示出来,那么同样的手链肯定会变成相同的状态,比如第二组数据
     
    原串    最小表示法(字典序最小的串)
    1010 --> 0101
    0101 --> 0101
    1000 --> 0001
    0001 --> 0001
     
    这样就比较容易判断是否相同了,可以使用字典树来判断这个串是否出现过。
     
    代码如下:
    ==========================================================================================================
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<stdlib.h>
    using namespace std;
    
    const int MAXM = 2;
    const int MAXN = 1007;
    
    struct node
    {
        node *next[MAXM];
    };
    
    bool BuildTrie(node *head, char s[])
    {///建立字典树,如果s已经存在返回0,否则返回1
        node *p = head;
        bool newNode = false;
    
        for(int i=0; s[i]; i++)
        {
            int k = s[i]-'0';
    
            if(p->next[k] == NULL)
            {
                newNode = true;
                p->next[k] = new node();
            }
            p = p->next[k];
        }
    
        return newNode;
    }
    void FreeTrie(node *head)
    {
        node *p = head;
    
        for(int i=0; i<MAXM; i++)
        {
            if(p->next[i] != NULL)
                FreeTrie(p->next[i]);
        }
    
        free(p);
    }
    int GetMinOrder(char s[], int N)
    {///求出来最小表示的首位置
        int i=0, j=1;
    
        while(i<N && j<N)
        {
            int k=0;
    
            while(s[i+k] == s[j+k] && k<N)
                k++;
    
            if(k == N)break;
    
            if(s[i+k] < s[j+k])
            {
                if(j+k > i)
                    j = j+k+1;
                else
                    j = i+1;
            }
            else
            {
                if(i+k > j)
                    i = i+k+1;
                else
                    i = j+1;
            }
        }
    
        return min(i, j);
    }
    
    int main()
    {
        int N;
    
        while(scanf("%d", &N) != EOF)
        {
            char s[MAXN]={0}, p[MAXN];
            node *head = new node();
            int ans = 0, len=0;
    
            while(N--)
            {
                scanf("%s", p);
                if(!len)len = strlen(p);
    
                strcpy(s, p);
                strcat(s, p);
    
                int MinIndex = GetMinOrder(s, len);
                strncpy(p, s+MinIndex, len);///把这个串转换成它的最小表示
    
                ans += BuildTrie(head, p);
            }
    
            printf("%d
    ", ans);
    
            FreeTrie(head);
        }
    
        return 0;
    }
  • 相关阅读:
    习题8-2 在数组中查找指定元素 (15分)
    习题8-1 拆分实数的整数与小数部分 (15分)
    练习8-8 移动字母 (10分)
    练习8-2 计算两数的和与差 (10分)
    习题6-6 使用函数输出一个整数的逆序数 (20分)
    狼人杀心得
    PHP配置文件详解
    15个实用的PHP正则表达式
    浅谈 PHP 中的多种加密技术及代码示例
    每个程序员都应该知道的 16个最佳 PHP 库
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4742692.html
Copyright © 2020-2023  润新知