题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2609
题目大意:给你一些串,问有多少个串是循环同构之后仍不同的
思路:典型的最小表示法题,对每一个串求一个最小循环表示,然后用set去重就好了
AC代码:
#include<bits/stdc++.h>
using namespace std;
char str[105], str2[205];
set<string> pp;
int minr(char s[], int l)
{
int i = 0, j = 1, k = 0;
while(i < l && j < l && k < l){
if(s[i+k] == s[j+k]) k++;
else{
if(s[i+k] < s[j+k]) j += k+1;
else i += k+1;
k = 0;
if(i == j) j++;
}
}
return min(i, j);
}
int main()
{
int T;
while(~scanf("%d", &T)){
pp.clear();
while(T--){
cin >> str;
int len = strlen(str);
for(int i = 0; i < len; i++){
str2[i] = str[i];
}
for(int i = 0; i < len; i++){
str2[i+len] = str[i];
}
int t = minr(str2, len);
str2[t+len] = '\0';
pp.insert(str2+t);
}
cout << pp.size() << '\n';
}
return 0;
}
附上最小表示法的模板:
int minr(char s[], int l) //返回最小循环表示开始的位置
{
int i = 0, j = 1, k = 0;
while(i < l && j < l && k < l){
if(s[i+k] == s[j+k]) k++;
else{
if(s[i+k] < s[j+k]) j += k+1;
else i += k+1;
k = 0;
if(i == j) j++;
}
}
return min(i, j);
}
int t = minr(str2, len); //str2 = 2*str
str2[t+len] = '\0';
printf("%s", str2+t); //最小循环表示