hdu 3374 String Problem (最大最小表示法)

http://acm.hdu.edu.cn/showproblem.php?pid=3374

SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7

题意:输出的是最小字典序的编号,最小字典序个数,最大字典序编号,最大字典序个数

求有几个这样的字符串直接Kmp求得next数组就ok了,

然后用最小表示法求出字典序最小的,用最大表示法求出字典序最大的

最大最小表示法详解

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>

using namespace std;

#define N 1100000
#define met(a, b) memset(a, b, sizeof(a))

const double PI = acos(-1.0);

typedef long long LL;

int Next[N];
char str[N], s[N];

int Min_Repre ()///最小表示法
{
    int i = 0, j = 1, k = 0;
    met (str, 0);

    int len = strlen (s);

    strcpy (str, s);
    strcat (str, s);

    while (i<len && j<len && k<len)
    {
        int t = str[ (i+k)%len ] - str[ (j+k)%len ];

        if (!t) k++;
        else
        {
            if (t>0) i = i+k+1;
            else j = j+k+1;

            if (i==j) j++;
            k = 0;
        }
    }
    return min (i, j);
}

int Max_Repre ()///最大表示法
{
    int i = 0, j = 1, k = 0;
    met (str, 0);

    int len = strlen (s);
    strcpy (str, s);
    strcat (str, s);

    while (i<len && j<len && k<len)
    {
        int t = str[ (i+k)%len ] - str[ (j+k)%len ];

        if (!t) k++;

        else
        {
            if (t<0) i = i+k+1;
            else j = j+k+1;

            if (i==j) j++;
            k = 0;
        }
    }
    return min (i, j);
}

int Get_Next ()
{
    int i = 0, j = -1;
    Next[i] = j;

    int len = strlen (s);

    while (i<len)
    {
        if (j==-1 || s[i] == s[j])
            Next[++i] = ++j;
        else j = Next[j];
    }

    int l = len - Next[len];
    if (len % l) return 1;
    return len/l;
}

int main ()
{
    while (scanf ("%s", s) != EOF)
    {
        met (Next, 0);

        int ans = Get_Next ();
        int a1 = Min_Repre ();
        int a2 = Max_Repre ();

        printf ("%d %d %d %d\n", a1+1, ans, a2+1, ans);
    }
    return 0;
}


你可能感兴趣的:(hdu 3374 String Problem (最大最小表示法))