• 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;
    }
  • 相关阅读:
    Ubuntu下VSFTPD(五)(匿名FTP设置方法)
    Ubuntu下VSFTPD(六)(常见FTP命令及其功能) (
    ubuntu13.04装配oracle11gR2
    oracle之报错:ORA-00054: 资源正忙,要求指定 NOWAIT_数据库的几种锁
    oracle建索引的可选项
    Oracle自定义函数
    C# WinForm开发系列
    为C#自定义控件添加自定义事件
    python 爬虫抓取心得
    C# 正则表达式学习
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4742692.html
Copyright © 2020-2023  润新知