先上题目:
How many
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1330 Accepted Submission(s): 523
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
题意:给出n个只有0和1的字符串,然后问你有多少个不同的串。
做法:先求出每一个字符串的最小表示,然后通过比较不同字符串的最小表示求出结果。
关于字符串的最小表示法,网上有相关资料,这里讲一下我的理解。
先看代码:
1 char e[102]; 2 int st,k; 3 4 void setMin() 5 { 6 k=strlen(e); 7 int i=0,j=1,l=0,d; 8 while(i0) i=i+l+1;15 else j=j+l+1;16 if(i==j) j++;17 l=0;18 }19 }20 st=min(i,j);21 }
先说一下朴素算法:枚举开头,然后比较以这些开头的字符串,找出最小的那一个。复杂度为(字符串长度*字符串长度)。
然后再说一下优化以后的算法:我们一开始先以下标为0(i)和下标为1(j)的两个字符串作为起始点。然后比较,当我们发现e[(i+l)%k]!=e[(j+l)%k]的时候,我们就将比较大的那边的指针移动到(x+l+1)的位置,从而跳过多次多余的比较,为什么这样是成立的呢?关于这一部分的解释还不能表达清楚。
/*这只是大概···,还没有写完。
如果e[i```]<e[j```] && i<j,那么j就会跳到更后的位置,而如果当前i的位置并不是最小的位置的话,那在以后的比较的时候就有可能跳到当前j~j+l+1的位置上,如果不跳到那些位置,就说明变化后的j的位置开始的字符串更小。
*/
上代码:
1 #include2 #include 3 #include 4 #define min(x,y) (x < y ? x : y) 5 #define MAX 10002 6 using namespace std; 7 8 typedef struct str{ 9 char c[102];10 bool operator < (const str& o)const{11 return strcmp(c,o.c)<0;12 }13 }str;14 str ss[MAX];15 16 char e[102];17 int st,k;18 19 void setMin()20 {21 k=strlen(e);22 int i=0,j=1,l=0,d;23 while(i 0) i=i+l+1;30 else j=j+l+1;31 if(i==j) j++;32 l=0;33 }34 }35 st=min(i,j);36 }37 38 int main()39 {40 int n;41 while(scanf("%d",&n)!=EOF)42 {43 for(int i=0; i