题目大意:
题目要求就是要我们找出不同的项链串有多少条,那么怎么判断他们是是否为同一条项链呢:比如给出字符串 0110 那么将这个字符串(也就是项链旋转)可以得到 0110->1100->1001->0011->0110 那么这些字符串其实都是这个属于这个字符串。
分析:
把它看做项链,那么不管我们怎么旋转一条项链,不管我们以哪个位置为起始点,它的本质还是这条项链没有变。这里其实设计到了一个算法-->“字符串的最小表示法” ,推荐一篇博文,个人觉得讲得还可以恩: http://blog.csdn.net/cclsoft/article/details/5467743
刚开始写这题的时候我也是进入了一个误区,导致了一直WA后来还因为数组开小了,提示超时(这个还真是没搞明白,应该提示RE才对);开始的时候一直以为,每条项链都是(也就是每个字符串都是旋转一次得到了下一个字符串),所以认为是简单的模拟,在对题目的判断上就出错了,其实题目可以给出 这样的数据 比如 1100 0011 而不是1100 1001,其实它还是同一串项链,也就是说他们的最小串是相等的;然后用解决了这个问题,又出现了个新的问题,就是同一条项链在题目中给出的顺序可能有差别 比如 1100 1000 1001 0100 其实这里只有两串不同的项链,但是可能我给的算法就会给出答案 4;所以这里我们需要把相同的项链归到一起,那么我们只要对其排个序就好了(sort一下)相同的就到一起了,然后就好处理了;
用“字符串的最小表示法”,可以确定了,最小的串在原串中的起始位置,那么我们就可以根据这个直接将最小串给表示出来,然后找出不一样的最小串有多少个就可以得出有多少条不同的项链了;然后用sort排序下将相同的项链放到一起,然后循环查找下,当找到了前面和后面有不一样的最小串的时候,那么其就是不同的项链;最终得到答案;
给出AC代码:
#include
#include
#include
#include
using namespace std;
struct neNODE
{
char strs[1005];
}necklace[10005];
char str[1005];
bool cmp(neNODE a, neNODE b)
{
return strcmp(a.strs,b.strs)<0;
}
int MinimumRepresentation(char *s, int l)
{
int i = 0, j = 1, k = 0, t;
while (i < l && j < l && k < l) {
t = s[(i + k) >= l ? i + k - l : i + k] - s[(j + k) >= l ? j + k - l : j + k];
if (!t) k++;
else{
if (t > 0) i = i + k + 1;
else j = j + k + 1;
if (i == j) ++j;
k = 0;
}
}
return (i < j ? i : j);
}
int main()
{
int n;
while (cin>>n)
{
int len;
for (int i = 0; i < n; i++)
{
cin >> str;
len = strlen(str);
int Minpos = MinimumRepresentation(str, len);//用最小串表示法得到最小串在原串中的起始位置;
int k, j;
for (k = 0, j = Minpos; j < len; j++) //得到最小串
{
necklace[i].strs[k++] = str[j];
}
for (j = 0; j < Minpos; j++)//得到最小串
{
necklace[i].strs[k++] = str[j];
}
necklace[i].strs[k] = '\0';
}
int count = 1;
sort(necklace, necklace + n, cmp); //排序,将相同的项链放到一起
for (int i = 1; i < n; i++)
{
if (strcmp(necklace[i].strs, necklace[i - 1].strs) != 0)
{
//cout << se << endl;
count++;
}
}
cout << count << endl;
}
return 0;
}