HDU 2609 How many (最大最小表示法)

How many

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2184    Accepted Submission(s): 904

Problem Description

Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100,tell me
How many kinds of necklaces total have.(if two necklaces can equal by rotating ,we say the two necklaces are some).
For example 0110 express a necklace, you can rotate it. 0110 -> 1100 -> 1001 -> 0011->0110.

Input

The input contains multiple test cases.
Each test case include: first one integers n. (2<=n<=10000)
Next n lines follow. Each line has a equal length character string. (string only include ‘0‘,‘1‘).

Output

For each test case output a integer , how many different necklaces.

Sample Input

4
0110
1100
1001
0011
4
1010
0101
1000
0001

Sample Output

1
2

用最小表示法返回字符串能旋转的最小的字典序。set记录一下数一数就好了。最大表示法和最小表示法基本上一样,就是判断的语句换了一下。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <set>
using namespace std;
const int maxn = 1e4 + 10;
char s[maxn][110];
int len;
set<string> st;

int GetMin(int id) {
    int i = 0, j = 1, k = 0;
    while(i < len && j < len && k < len) {
        int t = s[id][(i + k) % len] - s[id][(j + k) % len];
        if(!t) k++;
        else {
            if(t < 0) j = j + k + 1;
            else i = i + k + 1;
            if(i == j) j++;
            k = 0;
        }
    }
    return min(i, j);
}

/*int getMax() {
    int i = 0, j = 1, k = 0;
    while(i < len && j < len && k < len) {
        int t = s[(i + k) % len] - s[(j + k) % len];
        if(!t) k++;
        else {
            if(t > 0) j = j + k + 1;
            else i = i + k + 1;
            if(i == j) j++;
            k = 0;
        }
    }
    return min(i, j);
}*/

int main() {
    int n;
    while(~scanf("%d", &n)) {
        st.clear();
        for(int i = 1; i <= n; i++) {
            scanf("%s", s[i]);
        }
        for(int i = 1; i <= n; i++) {
            string tmp;
            len = strlen(s[i]);
            int Min = GetMin(i);
            for(int j = 0; j < len; j++) {
                tmp += s[i][(Min + j) % len];
            }
            //if(!st[tmp])
                st.insert(tmp);
        }
        cout << st.size() << endl;
    }
}
时间: 2024-10-10 07:43:39

HDU 2609 How many (最大最小表示法)的相关文章

hdu 2609 How many(最小表示法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2609 题意:给你n个字符串每个字符串可以左右移动但还是同一串比如 0110 可以表示为 0110 -> 1100 -> 1001 -> 0011->0110 这些都属于同一个字符串,最后问这n个字符串里一共有多少不同的字符串 可以将这些字符串都以其最小表示方法存下来复杂度为O(n)然后在sort一遍找一下有几个不同的就行了. #include <iostream> #inc

HDU 4162 Shape Number (最小表示法)

题意:给你一串n个数,求出循环来看一阶差的最小字典序:数字串看成一个顺时针的环,从某一点开始顺时针循环整个环,保证字典序最小就是答案 例如给你 2 1 3 就会得到(1-2+8 注意题意负数需要加8) (3-1) (2-3+8)-> 7 2 7 答案就是2 7 7. 典型的最小表示法.线性时间内求出最小字典序. 首先复制一遍数字串在原串后面,这样从原串任意位置开始向再后n个位置就是答案.接着双指针维护,直接双指针暴力比较数字串,当出现不同数字时,就把字典序大的那个指针向后移动尽量多的位置这样可以

HDU 3374 exkmp+字符串最大最小表示法

题意 找到一个字符串中最先出现的最小(大)表示位置,和最小(大)表示串出现次数 分析 用最小(大)表示法求出最先出现的最小(大)表示位置,然后将串长扩两倍用exkmp找出现次数. Code #include<bits/stdc++.h> #define fi first #define se second #define lson l,mid,p<<1 #define rson mid+1,r,p<<1|1 #define pb push_back #define ll

hdu 2609 How many 最小表示法

How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1248    Accepted Submission(s): 486 Problem Description Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100

[最小表示法] hdu 2609 How many

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2609 How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1225    Accepted Submission(s): 476 Problem Description Give you n ( n < 10000) nec

HDU 2609 最小表示法

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2609 题意:给定n个循环链[串],问有多少个本质不同的链[串](如果一个循环链可以通过找一个起点使得和其他串相同,那么就认为这2个链是一样的.就是求不同构的串) 思路:对于求同构串可以用最小表示法,然后判断是否相等就可以知道这2个是否是同构了.判重用的是set #define _CRT_SECURE_NO_DEPRECATE #include<iostream> #include<cstdi

hdu 2609 How many (最小表示法)

题意 给 \(n\) 个循环串,求本质不同串的数量 传送门 思路 最小表示法求下标,从最小下标处作为串的起点,将新串放到map中去重,最终map中的元素数量即为最终答案. 最小/大表示法 Code #include <cstdio> #include <cstring> #include <map> #include <string> using namespace std; const int maxn = 1e6+10; int n, l; char s

HDU 4162 Shape Number(字符串,最小表示法)

HDU 4162 题意: 给一个数字串(length <= 300,000),数字由0~7构成,求出一阶差分码,然后输出与该差分码循环同构的最小字典序差分码. 思路: 第一步是将差分码求出:s[i] = (s[i] - s[i+1] + 8) % 8; 第二步是求出最小字典序的循环同构差分码,我之前没注意到字符串规模..直接用set做,MLE+TLE... 正确的方式应该是一种O(n)的解法,即最小表示法.//关于最小表示法的证明与详述请参考最小表示法:) 最小表示法算法: 初始时,i=0,j=

Hdu 5442 Favorite Donut (2015 ACM/ICPC Asia Regional Changchun Online 最大最小表示法 + KMP)

题目链接: Hdu 5442 Favorite Donut 题目描述: 给出一个文本串,找出顺时针或者逆时针循环旋转后,字典序最大的那个字符串,字典序最大的字符串如果有多个,就输出下标最小的那个,如果顺时针和逆时针的起始下标相同,则输出顺时针. 解题思路: 看到题目感觉后缀数组可以搞,正准备犯傻被队友拦下了,听队友解释一番,果断丢锅给队友.赛后试了一下后缀数组果然麻烦的不要不要的(QWQ),还是最大最小表示法 + KMP来的干净利索. 最大表示法:对于一个长度为len文本串,经过循环旋转得到长度