HDU 4333 Revolving Digits

题目链接:HDU4333

题意:一个数字串依次向前移动,问有几个不同的比原串大的,比原串小的,以及与原串相等的。注意是不同的!!!!

题目分析:这题应该有很多不同的解法吧,我是为了学习EXKMP所以用扩展KMPA掉了。先利用KMP求出原串的循环节,这里求相同字符串个数的与之前HDU3374是一样的。为了节省空间,之后扩展KMP也使用nexts数组开下的空间。get_extand用原串与原串匹配,由于nexts数组记录最大公共前缀的位置,所以比较第一个不匹配的位置判断是大于还是小于。

//
//  main.cpp
//  HDU4333
//
//  Created by teddywang on 16/3/9.
//  Copyright © 2016年 teddywang. All rights reserved.
//

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int len,nexts[1000005];
char s[1000005];
void get_next(char *a,int l)
{
    int i=0,j=-1;
    nexts[0]=-1;
    while(i<l)
    {
        if(j==-1||a[i]==a[j])
        {
            nexts[++i]=++j;
        }
        else j=nexts[j];
    }
}

void get_extend(char *a,int l)
{
    int i=0,j=1;
    nexts[0]=l;
    while(a[i]==a[i+1]&&i+1<l) i++;
    nexts[1]=i;
    i=1;
    while(++j<l/2)
    {
        int maxr=i+nexts[i]-1;
        nexts[j]=min(nexts[j-i],max(maxr-j+1,0));
        while(j+nexts[j]<l&&a[nexts[j]]==a[j+nexts[j]]) nexts[j]++;
        if(i+nexts[i]<j+nexts[j]) i=j;
    }
}

int main()
{
    int T;
    cin>>T;
    for(int i=1;i<=T;i++)
    {
        scanf("%s",s);
        len=strlen(s);
        get_next(s, len);
        int temp=(len%(len-nexts[len])==0 ? len/(len-nexts[len]):1);
        for(int j=len;j<2*len;j++)
        {
            s[j]=s[j-len];
        }
        get_extend(s, 2*len);
        int l=0,e=0,g=0;
        for(int j=0;j<len;j++)
        {
            if(nexts[j]>=len) e++;
            else if(s[nexts[j]]>s[j+nexts[j]]) l++;
            else g++;
        }
        printf("Case %d: %d %d %d\n",i,l/temp,e/temp,g/temp);
    }
}


你可能感兴趣的:(KMP,扩展)