【最小表示法】HDU2069How many【模板】

来源:互联网 发布:电饭煲型号推荐 知乎 编辑:程序博客网 时间:2024/06/05 16:31

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2609

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
4011011001001001141010010110000001
 

Sample Output
12
题目意思:

有n个有01组成的字符串,每个字符串都代表一个项链,那么该字符串就是一个环状的结构,求可以经过循环旋转,最后不同的串有多少个

思路:

最小表示法的思路相当于模拟;不过加了一个类似于next数组性质的k,提高的算法的效率,时间复杂度O(n);

起始假定最小表示是从i=0开始,那么我们就从j=1开始比较,寻找更小的表示方法。

这里比较有三种情况:

1、s[i]>s[j]  说明i,j相比而言,j是更小的表示起点;

2、s[i]<s[j]  说明i,j相比较而言,i是更小的表示起点;

3、s[i]=s[j]  说明i,j相比,两个点目前大小一样,我们需要比较i,j后面的字符谁大谁小。

这里第三种情况,我们就可以用类似于next数组的方法,用一个k来标记比较i,j后面的字符,当出现不同的时候我们就可以直接的跳到i+k/j+k后面,提高代码效率;

代码:

#include<iostream>#include<set>#include<string>#include<cstring>#include<cstdio>using namespace std;int minRepressStation(string s,int len){    int i=0,j=1,k=0;    while(i<len&&j<len&&k<len){        int tmp=s[i+k]-s[j+k];        if(tmp==0) k++;         //  i+k和j+k位置字符串相同;        else{                   //      不相等的情况;            if(tmp>0) i+=k+1;   //  s[i+k]>s[j+k]的情况,那最小起始位置就要往后移k+1位;            else j+=k+1;        //  s[i+k]<s[j+k]的情况,最小位置不变,j往后移k+1位;            if(i==j) j++;       //  如果移完之后i和j相等,则j++,这是假定的情况,i,j是相对而言的情况;i++也是一样的            k=0;                //  调换位置后,要重新将k置0;        }    }    return min(i,j);}int main(){    int n;    string s;    while(cin>>n){        set<string>q;        for(int i=0;i<n;i++){            cin>>s;            int len=s.size();            s=s+s;            int k=minRepressStation(s,len);            s=s.substr(k,len);            q.insert(s);        }        cout<<q.size()<<endl;    }    return 0;}


0 0
原创粉丝点击