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
题意:
给一些长度相同的01数列,要求不重复循环串的个数(经过循环相同的也算相同)
如0110和1100,1001,0011都算相同串
思路:
用最小表示法处理每个串,就可以把循环串都变成相同的。然后用set容器去重
注意:substr函数是对于字符串而言的,所以先需将字符数组强制转化为字符串在进行操作
代码:
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<string>
using namespace std;
const int MAXM=1000005;
char P[MAXM];
string str;
int f[MAXM],dp[MAXM];
int m;
void getFail(char *P,int *f)
{
f[0]=f[1]=0;
for(int i=1;i<m;i++)
{
int j=f[i];
while(j && P[i]!=P[j]) j=f[j];
f[i+1]=(P[i]==P[j])?j+1:0;
}
}
//最小表示法
int get_minstring(char *s)
{
int len = strlen(s);
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==0)
k++;
else
{
if(t > 0)
i+=k+1;
else
j+=k+1;
if(i==j) j++;
k=0;
}
}
return min(i,j);
}
int main()
{
int n;
while(cin>>n)
{
vector<string>v;
for(int i=0;i<n;i++)
{
cin>>P;
m=strlen(P);
str=(string)P;
str=str.substr(get_minstring(P),m-get_minstring(P))+str.substr(0,get_minstring(P));
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;
}