题意:给一个数字,每一次把它的最后一位拿到最前面,一直那样下去,分别求形成的数字小于,等于和大于原来数的个数。


SAM乱搞失败

当然要先变SS了

然后考虑每个后缀前长为n个字符,把它跟S比较就行了

如果用后缀家族的话复杂度要加上log,本题会TLE吧

一个串S的每个后缀与另一个串T的最长公共前缀可以用扩展KMP!复杂度O(n+m)

课件

从1开始写真不容易以后再也不从1开始了,判断位置好麻烦好容易错

next[i]=LCP(T[i,m],T)

extend[i]=LCP(S[i,n],T)

主要思想就是求i时记录p=max{a+extend[a]-1},1<=a<i 也就是当前最远匹配到哪里,这么做是为了以后直接利用next的信息

S[a,a+extend[a]-1]--->T[1,extend[a]-1]是一样的

那么从i开始的后缀的前一部分是和T[i-a+1..]相同的,就不用比较了因为已经有L=next[i-a+1]了

如果i+L-1<p,extend[i]=L

否则从s[p+1]和t[p-i+1+1]开始暴力往后匹配,并更新a

注意:本题要求不相同的数字,出现相同数字说明有循环节,KMP求一下看看有没有可以整除的循环节

#include <cstdio>
#include <cstring>
using namespace std;
const int N=2e6+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
inline int min(int a,int b){return a<b?a:b;}
inline int max(int a,int b){return a>b?a:b;}
int n,m;
int next[N],extend[N];
char s[N],t[N];
void getNext(char s[],int n){
//printf("getNext %d\n",n);
//for(int i=1;i<=n;i++) printf("%c",s[i]); next[]=n;
int a=;
while(a<n&&s[a]==s[a+]) a++;
next[]=a-;
a=;
for(int i=;i<=n;i++){
int p=a+next[a]-,L=next[i-a+];
if(i+L-<p) next[i]=L;
else{
int j=max(p-i+,);//!!
while(i+j<=n&&s[i+j]==s[j+]) j++;
next[i]=j;a=i;
}
}
//for(int i=1;i<=n;i++) printf("next %d %d\n",i,next[i]);
}
void getExtend(char s[],char t[]){
//printf("getExtend %d\n",n);
//for(int i=1;i<=n;i++) printf("%c",s[i]);puts("");
getNext(t,m);
int mn=min(n,m),a=;
while(a<=mn&&s[a]==t[a]) a++;
extend[]=a-;
a=;
for(int i=;i<=n;i++){
int p=a+extend[a]-,L=next[i-a+];
if(i+L-<p) extend[i]=L;
else{
int j=max(p-i+,);
while(i+j<=n&&s[i+j]==t[j+]) j++;
extend[i]=j;
a=i;
}
}
//for(int i=1;i<=n;i++) printf("extend %d %d\n",i,extend[i]);
}
int fail[N];
void getFail(char s[],int n){
fail[]=;
for(int i=;i<=n;i++){
int j=fail[i-];
while(j&&s[j+]!=s[i]) j=fail[j];
fail[i]=s[j+]==s[i]?j+:;
}
}
int L,E,G;
void solve(){
getExtend(s,t);
L=E=G=;
for(int i=;i<=m;i++){
int lcp=extend[i];
if(lcp>=m) E++;
else if(t[+lcp]<s[i+lcp]) G++;
else L++;
}
//for(int i=1;i<=n;i++) printf("hi %d %d %d\n",i,next[i],extend[i]);
getFail(t,m);
int _=m%(m-fail[m])==?m/(m-fail[m]):;
L/=_;E/=_;G/=_;
} int main(){
freopen("in","r",stdin);
int T=read(),cas=;
while(T--){
scanf("%s",s+);
n=m=strlen(s+);
for(int i=;i<=n;i++) s[i+n]=t[i]=s[i];
n<<=;
solve();
printf("Case %d: %d %d %d\n",++cas,L,E,G);
}
}

HDU 4333 Revolving Digits [扩展KMP]【学习笔记】的更多相关文章

  1. HDU 4333 Revolving Digits 扩展KMP

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意:给以数字字符串,移动最后若干位到最前边,统计得到的数字有多少比原来大,有多少和原来同样,有多少 ...

  2. HDU 4333 Revolving Digits 扩张KMP

    标题来源:HDU 4333 Revolving Digits 意甲冠军:求一个数字环路移动少于不同数量 等同 于的数字 思路:扩展KMP求出S[i..j]等于S[0..j-i]的最长前缀 推断 nex ...

  3. 字符串(扩展KMP):HDU 4333 Revolving Digits

    Revolving Digits Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  4. HDU - 4333 Revolving Digits(扩展KMP)

    http://acm.hdu.edu.cn/showproblem.php?pid=4333 题意 一个数字,依次将第一位放到最后一位,问小于本身的数的个数及等于本身的个数和大于本身的个数,但是要注意 ...

  5. 扩展KMP - HDU 4333 Revolving Digits

    Revolving Digits Problem's Link Mean: 给你一个字符串,你可以将该字符串的任意长度后缀截取下来然后接到最前面,让你统计所有新串中有多少种字典序小于.等于.大于原串. ...

  6. 【扩展kmp+最小循环节】HDU 4333 Revolving Digits

    http://acm.hdu.edu.cn/showproblem.php?pid=4333 [题意] 给定一个数字<=10^100000,每次将该数的第一位放到放到最后一位,求所有组成的不同的 ...

  7. HDU - 4333 Revolving Digits(拓展kmp+最小循环节)

    1.给一个数字字符串s,可以把它的最后一个字符放到最前面变为另一个数字,直到又变为原来的s.求这个过程中比原来的数字小的.相等的.大的数字各有多少. 例如:字符串123,变换过程:123 -> ...

  8. hdu4333 Revolving Digits(扩展kmp)

    Revolving Digits Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  9. Hdu 4333 Revolving Digits(Exkmp)

    Revolving Digits Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...

随机推荐

  1. android动画源码合集、动态主题框架、社交app源码等

    Android精选源码 仿MIUI果冻视图-BouncingJellyView   一个快速易用的动态主题框架   android动画效果集合源码   android使用Kotlin开发的Dribbb ...

  2. Spark性能调优之资源分配

    Spark性能调优之资源分配    性能优化王道就是给更多资源!机器更多了,CPU更多了,内存更多了,性能和速度上的提升,是显而易见的.基本上,在一定范围之内,增加资源与性能的提升,是成正比的:写完了 ...

  3. 用AngularJS实现对表格的增删改查(仅限前端)

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  4. 学习Lucene、solr之前应当了解的一些术语

    一些简单易理解术语,例如:词条搜索.语义信息.搜索引擎 搜索引擎分类:全文搜索(百度.谷歌).目录搜索.元搜索.垂直搜索 元搜索例子:360综合搜索.搜魅网(someta 集合了百度.google.搜 ...

  5. sha1() 函数

    sha1() 函数计算字符串的 SHA-1 散列. sha1() 函数使用美国 Secure Hash 算法 1. 来自 RFC 3174 的解释 - 美国 Secure Hash 算法 1:SHA- ...

  6. Linuxc - gdb调试程序

    指针实现变量交换值 #include <stdio.h> void change(int *a,int *b) { int tmp = *a; *a = *b;// 将指针a所在地址的值, ...

  7. [转]linux下centos服务器安全设置

    引言: 我们必须明白:最小的权限+最少的服务=最大的安全 所以,无论是配置任何服务器,我们都必须把不用的服务关闭.把系统权限设置到最小话,这样才能保证服务器最大的安全.下面是CentOS服务器安全设置 ...

  8. 本地计算机上的OracleOraDb10g_home1TNSListener服务启动后又停止了..........解决办法

    方法1.直接修改 listener.ora 我机器上的路径是: D:/Oracle/product/10.2.0/db_1/NETWORK/ADMIN/listener.ora 修改其中的 HOST ...

  9. junit4X系列--Assert与Hamcrest

    原文出处:http://www.blogjava.net/DLevin/archive/2012/05/12/377960.html.感谢作者无私分享 到目前,JUnit4所有的核心源码都已经讲解过了 ...

  10. Linux指令--ps

    Linux中的ps命令是Process Status的缩写.ps命令用来列出系统中当前运行的那些进程.ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻的那些进程,如果想要动态的显示进程信 ...