HDU 2609 How many (字串最小字典序+set去重)
題目連結
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
PS:題意大家都應該明白吧。題解:將字串看成環,如果一個字串通過旋轉得到的另一個字串,這兩個字串的最小字典序一定是一樣的。所以我們直接將每個字串的最小字典序壓入set中,如果有題中所說的一類的字串,那麼壓入的最小字典序的字串一定一樣,而set可以去重,所以最後set的大小,就是n個字串可以分成多少類,詳解看程式碼。
#include <iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<map> #include<queue> #include<set> #include<cmath> #include<stack> #include<string> const int maxn=1e2+10; const int mod=10007; const int inf=1e8; #define me(a,b) memset(a,b,sizeof(a)) #define lowbit(x) x&(-x) typedef long long ll; using namespace std; char str[maxn]; int len; set<string>q; int min_pos()//找到字串最小字典序的相應位置 { int p1=0,p2=1,k=0; while(p1<len&&p2<len&&k<len) { int temp=str[(p1+k)%len]-str[(p2+k)%len]; if(!temp) k++; else { temp>0?p1+=k+1:p2+=k+1; if(p1==p2) p2++; k=0; } } return min(p1,p2); } void Insert()//將每個字串以最小字典序插入set中 { char temp[maxn]; int pos=min_pos();//找字串的最小字典序位置 int l=0; for(int i=pos; i<len; i++)//將字串轉換成最小字典序形式 temp[l++]=str[i]; for(int i=0; i<pos; i++)//將字串轉換成最小字典序形式 temp[l++]=str[i]; temp[len]='\0'; q.insert(temp); } int main() { int n; while(scanf("%d",&n)!=EOF) { q.clear(); for(int i=0; i<n; i++) { scanf("%s",str); len=strlen(str); Insert(); } cout<<q.size()<<endl; } return 0; }