题目链接: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);
}
}