计蒜客 - 旋转数字

本文介绍了如何利用拓展KMP算法解决计蒜客给出的旋转数字问题。通过枚举旋转数字并利用字符串比较判断大小,同时解决循环节、前导零问题,最终得出小于、等于和大于原数的个数。
摘要由CSDN通过智能技术生成

计蒜客 - 旋转数字

蒜头君发现了一个很好玩的事情,他对一个数作旋转操作,把该数的最后的数字移动到最前面。比如,数 123123 可以得到 312, 231, 123312,231,123,这样就可以得到很多个数。

现在,蒜头君的问题是这些数中,有多少个不同的数小于原数,多少个等于原数,多少个大于原数。

旋转中可能会出现前导零,两数比较的时候可以忽略前导零的影响。

输入格式

输入一个整数 N ( 0 < N ≤ 1 0 100000 ) N(0 < N\leq 10^{100000}) N(0<N10100000)

341

输出格式

答案在一行中输出三个整数,分别是小于 N,等于 N,大于 N 的个数,中间以空格隔开。

1 1 1

这道题是一道利用拓展 KMP 算法的好题目。

我们一点一点来剖析这道题。

第一个问题,怎么枚举出所有旋转得到的数字?

把数字收尾相接,然后从第 0 个位置到第 length 个位置,每次往后取 length 个长度的字符,就可以遍历出所有可能的 length 个数字。

char num[MAX_LEN];
scanf("%s", num);
int len = strlen(num);
char* numnum = duplicate(num);
for (int i = 0; i < len; i++) {
   
    for (int j = i; j < i + len; j++) {
   
        printf("%c", numnum[j]);
    }
    printf("\n");
}
char* concat(const char* s1, const char* s2) {
   
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    char* s3 = (char*)malloc(sizeof(char) * (len1 + len2 + 1));
    strncpy(s3, s1, len1);
    strncpy(s3 + len1, s2, len2);
    s3[len1 + len2] = '\0';
    return s3;
}

char* duplicate(const char* s) {
   
    return concat(s, s);
}

第二个问题,怎么比较大小?

由于数字非常大,我们不可能每次都转成整型以后去比较大小,而利用字符串相等来比较数字之间的大小,是一种常用的做法。

首先让我们考虑怎么比较两个数字相等,显然,那就是这两个字符串相等,即 strcmp(s1, s2) == 0,对应到 KMP 算法中,那就是 next[s[i]] = length

parseInt(s1) === parseInt(s2)
// 等价于
s1 === s2

当然,这里忽略了前导零,因为 s1 = '001's2 = '01',显然 parseInt(s1) === parseInt(s2) 是成立的,但是 s1 === s2 是不成立的。

可是,由于题目要求的是不同的数字,所以我们不需要考虑重复数字,那么,在这种情况下,与原数相等的数字就只有

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凝神长老

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值