hdu2609 最小表示法

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.

InputThe 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‘). 
OutputFor 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题意:给一些长度相同的01数列,要求求出不相同的个数(经过循环相同的也算相同)题解:最小表示法(为啥分类到kmp里面?)直接水过了,还以为要kmp之类的呢

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define ll long long
#define mod 1000000007

using namespace std;

const int N=1000000+5,maxn=1000000+5,inf=1e9+5;

int Next[N],slen;
string str;

void getnext()
{
    Next[0]=-1;
    int k=-1;
    for(int i=1;i<slen;i++)
    {
        while(k>-1&&str[k+1]!=str[i])k=Next[k];
        if(str[k+1]==str[i])k++;
        Next[i]=k;
    }
}
int getmin()
{
    int i=0,j=1,k=0;
    while(i<slen&&j<slen&&k<slen){
        int t=str[(i+k)%slen]-str[(j+k)%slen];
        if(!t)k++;
        else
        {
            t>0 ? i=i+k+1 : j=j+k+1;
            if(i==j)j++;
            k=0;
        }
    }
    return min(i,j);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    while(cin>>n){
        vector<string>v;
        for(int i=0;i<n;i++)
        {
            cin>>str;
            slen=str.size();
            str=str.substr(getmin(),slen)+str.substr(0,getmin());
            bool flag=1;
            for(int j=0;j<v.size();j++)
                if(v[j]==str)
                {
                    flag=0;
                    break;
                }
            if(flag)v.push_back(str);
        }
        cout<<v.size()<<endl;
    }
    return 0;
}

时间: 2024-10-14 05:12:23

hdu2609 最小表示法的相关文章

hdu2609最小表示法

#include <iostream> #include <algorithm> #include <string.h> #include <cstdio> #include <vector> using namespace std; const int maxn=10005; struct elem { char str[105]; int len; bool operator <(const elem &rhs)const{ r

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=

最小表示法(模板)

最小表示法就是对于一个循环字符串,其字典序最小的状态: 显然任意一个循环串的最小表示法是唯一的,那么可以同过比较两个循环串的最小表示法来判断它们是否相同: 对于朴素算法: 初始化:i = 0, j = 1, k = 0; 若 s[i] < s[j],j++: 若 s[i] > s[j],i = j, j++: 若 s[i] == s[j],则 k++,直至 s[i + k] != s[j + k] 对于 s[i + k] < s[j + k],j++: 否则 i = j, j++: 返回

USACO 5.5.2 字符串的最小表示法

这道题是最小表示法的一个应用, 代码如下: /* ID: m1500293 LANG: C++ PROG: hidden */ #include <cstdio> #include <algorithm> #include <cstring> using namespace std; char s[100000 + 100]; int len; int mins(char s[], int len) { int i=0, j=1, k=0; while(i<len

【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game

给你一个n*m的字符矩阵,将横向(或纵向)全部裂开,然后以任意顺序首尾相接,然后再从中间任意位置切开,问你能构成的字典序最大的字符串. 以横向切开为例,纵向类似. 将所有横排从大到小排序,枚举最后切开的位置在哪一横排,将这一排提到排序后的字符串数组最前面,求个"最大表示法",如果最大表示法的位置恰好在第一排的位置,那么可以用来更新答案. 如果不在第一排的位置,那么其所构成的仍然是合法的串,而且一定不会影响答案. 这是一个最小表示法的板子. #include<cstdio>

BZOJ 2176 Strange string 最小表示法

题目大意:给定一个串S,求最小表示法 n<=1000W,实在不敢写后缀自己主动机,就去学了最小表示法= = 记得用unsigned char不然WA= = 数据真是逗- - #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 10001000 using namespace std; int n; unsigned char s[

循环字符串最大最小表示法模版

循环字符串最大最小表示法模版 定义字符串abcde和cdeab同构,因为abcde转两格即为cdeab,该字符串称为循环字符串. 循环字符串的字典序最小的同构字符串称为最小表示,最大表示同理. 这里只给模版,以后再深究. int getMin(char *s) ///返回首位置 { int n=strlen(s); int i=0,j=1,k=0; while(i<n&&j<n&&k<n){ int t=s[(i+k)%n]-s[(j+k)%n]; if(

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

51nod1282(最小表示法&amp;&amp;枚举)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1282 题意:中文题目诶- 思路:指针不可转,刻盘可转,显然,对于两组指针,当且仅当它们所有对应相邻指针间距都相等时是满足题意的: 先得到指针间距,因为刻盘可转,相当于循环数组,可以先求一下最小表示法,然后再两两枚举所有情况,对于最小表示法相同的两组指针,计数加一: 代码: 1 #include <iostream> 2 #include <algori