HDU-3374-String Problem (minimum notation, KMP)

link:

https://vjudge.net/problem/HDU-3374

Meaning of the questions:

Give you a string with length N, you can generate N strings by left shifts. For example let consider the string “SKYLONG”, we can generate seven strings:
String Rank
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once.
Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.

Ideas:

Minimum showing a computation method, maximum and minimum string dictionary sequence,
kmp seeking loop section.
But the data do not seem strong,
abcabcabca and aabcabcabc, the number of cycles of two sets of data answer came out different, but after a
do not know the title I did not understand.

Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
//#include <memory.h>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <stack>
#include <string>
#include <assert.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#define MINF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 1e6+10;
const int MOD = 1e4+7;

char ori[MAXN];
int Next[MAXN];

int GetMin(char *s)
{
    //字符串的最小表示法
    int len = strlen(s);
    int i = 0, j = 1, k = 0;
    //i为第一个字符串的开头, j为第二个字符串的开头, k为长度.
    while (i < len && j < len && k < len)
    {
        int cmp = s[(i+k)%len]-s[(j+k)%len];
        if (cmp == 0)
            k++;
        else
        {
            if (cmp > 0)
                i += k + 1;
            else
                j += k + 1;
            if (i == j)
                j++;
            k = 0;
        }
    }
    return min(i, j);
}

int GetMax(char *s)
{
    //字符串的最大表示法
    int len = strlen(s);
    int i = 0, j = 1, k = 0;
    //i为第一个字符串的开头, j为第二个字符串的开头, k为长度.
    while (i < len && j < len && k < len)
    {
        int cmp = s[(i+k)%len]-s[(j+k)%len];
        if (cmp == 0)
            k++;
        else
        {
            if (cmp < 0)
                i += k + 1;
            else
                j += k + 1;
            if (i == j)
                j++;
            k = 0;
        }
    }
    return min(i, j);
}

void GetNext(char *t)
{
    int i = 0, k = -1;
    int len = strlen(t);
    Next[0] = -1;
    while (i < len)
    {
        if (k == -1 || t[i] == t[k])
        {
            ++i;
            ++k;
            Next[i] = k;
        }
        else
            k = Next[k];
    }
}

int main()
{
    while (~scanf("%s", ori))
    {
        int mmin = GetMin(ori);
        int mmax = GetMax(ori);
        int len = strlen(ori);
        GetNext(ori);
        int cyc = len/(len-Next[len]);
        printf("%d %d %d %d\n", mmin+1, cyc, mmax+1, cyc);
    }

    return 0;
}

Guess you like

Origin www.cnblogs.com/YDDDD/p/11594575.html