计蒜客习题:旋转数字


问题描述

蒜头君发现了一个很好玩的事情,他对一个数作旋转操作,把该数的最后的数字移动到最前面。比如,数 123 可以得到 312, 231,123这样就可以得到很多个数。
现在,蒜头君的问题是这些数中,有多少个不同的数小于原数,多少个等于原数,多少个大于原数。
旋转中可能会出现前导零,两数比较的时候可以忽略前导零的影响。
输入格式
输入一个整数 N(0 < N <1e100000)。
输出格式
答案在一行中输出三个整数,分别是小于 NN,等于 NN,大于 NN 的个数,中间以空格隔开。
样例输入
3 4 1
样例输出
1 1 1


AC代码


#include<iostream>
#include<string>
#include<string.h>
#include<algorithm>
#include<map>
using namespace std;
string num;
int n;
int tmp[200010];
int Next[200010];
void get_tmp(string s) {
    tmp[0] = 0;
    for (int i = 1; i < s.size(); i++) {
        int j = tmp[i - 1];
        while (j && s[i] != s[j]) {
            j = tmp[j];
        }
        tmp[i] = s[i] == s[j] ? j + 1 : 0;
    }
}
void get_Next(string s) {
    Next[0] = s.size();
    int j = 0, k = 1, t, l; 
    while (j + 1 < s.size() && s[j] == s[j + 1])j++;
    Next[1] = j;
    for (int i = 2; i < s.size(); i++) {
        j = k + Next[k] - 1; 
        l = Next[i - k];
        if (i + l - 1 < j) {
            Next[i] = l;
        }
        else {
            t = max(0, j - i + 1);
            while (i + t < s.size() && s[i + t] == s[t])t++;
            Next[i] = t; k = i;
        }
    }
}
int main() {
    cin >> num;
    num = num + num;
    get_tmp(num);
    n = num.size() / 2;
    if (tmp[num.size() - 1] > n) {
        n = num.size() - tmp[num.size() - 1];
    }
    get_Next(num);
    int xiao = 0;
    int deng = 1;
    int da = 0;
    for (int i = 0; i < n; i++) {
        if (Next[i] < n) {
            if (num[i + Next[i]] < num[Next[i]]) {
                xiao++;
            }
            else {
                da++;
            }
        }
    }
    cout << xiao << " " << deng << " " << da << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liukairui/article/details/80622324