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

例如:字符串123,变换过程:123 -> 312 -> 231 -> 123

因为:312>123, 231>123, 123=123

所以答案是:0 1 2

2、令str1=s,str2=s+s,然后str1作为子串,str2作为主串,进行扩展kmp求出str2[i...len2-1]与str1[0...len1-1]的最长公共前缀。当公共前缀==len1时,两个数相等;否则,只须比较公共前缀后的下一个字符就能判断大小了。

注意当中有重复的情况,只有当s有循环节的时候才会出现,先求出s的最小循环节,然后用s的长度除以最小循环节得到循环节的个数,将3个结果都除以循环节个数即可。

3、

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std; #define MaxSize 200005 int _next[MaxSize],extend[MaxSize]; //扩展kmp
//next[i]:x[i...m-1]与x[0...m-1]的最长公公前缀
//extend[i]:y[i...n-1]与x[0...m-1]的最长公共前缀
void pre_EKMP(char x[],int m,int _next[]){//m长度
_next[]=m;
int j=;
while(j+<m&&x[j]==x[j+])j++;
_next[]=j;
int k=;
for(int i=;i<m;i++){
int p=_next[k]+k-;
int L=_next[i-k];
if(i+L<p+)_next[i]=L;
else{
j=max(,p-i+);
while(i+j<m&&x[i+j]==x[j])j++;
_next[i]=j;
k=i;
}
}
} void EKMP(char x[],int m,char y[],int n,int _next[],int extend[]){//x子串,m子串长度,y主串,n主串长度
pre_EKMP(x,m,_next);
int j=;
while(j<n&&j<m&&x[j]==y[j])j++;
extend[]=j;
int k=;
for(int i=;i<n;i++){
int p=extend[k]+k-;
int L=_next[i-k];
if(i+L<p+)extend[i]=L;
else{
j=max(,p-i+);
while(i+j<n&&j<m&&y[i+j]==x[j])j++;
extend[i]=j;
k=i;
}
}
}
/*
子串 :a b a b
主串 :a b a b a c
next :4 0 2 0
extend:4 0 3 0 1 0
*/
void GetNext(char t[]){//求next数组
int j,k,len;
j=;//从0开始,首先求_next[1]
k=-;//比较指针
_next[]=-;//初始值-1
len=strlen(t);
while(j<len){
if(k==-||t[j]==t[k]){//指针到头了,或者相等
++j;
++k;
_next[j]=k;//此句可由优化替代
/*优化(求匹配位置时可用)
if(t[j]!=t[k])_next[j]=k;
else _next[j]=_next[k];
//*/
}
else k=_next[k];
}
}
int main(){
char str1[],str2[];//子串,主串
int i,j,len1,len2;//子串长度,主串长度
int T;
int sumL,sumE,sumG;
scanf("%d",&T);
for(i=;i<=T;++i){
sumL=sumE=sumG=;
scanf("%s",str1);
strcpy(str2,str1);
strcat(str2,str1);
len1=strlen(str1);
len2=strlen(str2);
EKMP(str1,len1,str2,len2,_next,extend);
for(j=;j<len1;++j){
if(extend[j]==len1)++sumE;
else if(str2[j+extend[j]]<str1[extend[j]])++sumL;
else ++sumG;
}
GetNext(str1);
int repetend=len1-_next[len1];//最小循环节
int numR;//循环节的个数
if(len1%repetend==)numR=len1/repetend;
else numR=;
printf("Case %d: %d %d %d\n",i,sumL/numR,sumE/numR,sumG/numR);
} return ;
}

HDU - 4333 Revolving Digits(拓展kmp+最小循环节)的更多相关文章

  1. HDU 4333 Revolving Digits 扩张KMP

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

  2. HDU 3746 Cyclic Nacklace(KMP+最小循环节)题解

    思路: 最小循环节的解释在这里,有人证明了那么就很好计算了 之前对KMP了解不是很深啊,就很容易做错,特别是对fail的理解 注意一下这里getFail的不同含义 代码: #include<io ...

  3. HDU 4333 Revolving Digits 扩展KMP

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

  4. HDU 4333 Revolving Digits [扩展KMP]【学习笔记】

    题意:给一个数字,每一次把它的最后一位拿到最前面,一直那样下去,分别求形成的数字小于,等于和大于原来数的个数. SAM乱搞失败 当然要先变SS了 然后考虑每个后缀前长为n个字符,把它跟S比较就行了 如 ...

  5. hdu 4333"Revolving Digits"(KMP求字符串最小循环节+拓展KMP)

    传送门 题意: 此题意很好理解,便不在此赘述: 题解: 解题思路:KMP求字符串最小循环节+拓展KMP ①首先,根据KMP求字符串最小循环节的算法求出字符串s的最小循环节的长度,记为 k: ②根据拓展 ...

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

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

  7. 扩展KMP - HDU 4333 Revolving Digits

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

  8. HDU 4333 Revolving Digits

    扩展KMP的应用 我们发现本题的关键在于如何高效的判断两个同构字符串的大小关系,想到如果能够预处理出每一个同构字符串与原字符串的最长公共前缀,那么直接比较它们不一样的部分就好,扩展KMP正好是用来处理 ...

  9. HDU 1358 Period(KMP+最小循环节)题解

    思路: 这里只要注意一点,就是失配值和前后缀匹配值的区别,不懂的可以看看这里,这题因为对子串也要判定,所以用前后缀匹配值,其他的按照最小循环节做 代码: #include<iostream> ...

随机推荐

  1. bootspring + mybaits +mysql Date 类型的处理

    mysql 中有date 类型的属性,java实体类中对应的属性是java.sql.Date 类的. 最初的bug是怎么新增,joinDate 值都是null. 千辛万苦学会了用String转Date ...

  2. Leetcode 264.丑数II

    丑数II 编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, 8, 9, 10 ...

  3. 77. Spring Boot Use Thymeleaf 3【从零开始学Spring Boot】

    [原创文章,转载请注明出处] Spring Boot默认选择的Thymeleaf是2.0版本的,那么如果我们就想要使用3.0版本或者说指定版本呢,那么怎么操作呢?在这里要说明下 3.0的配置在spri ...

  4. 2016上海站EC-final总结!

    2016上海站EC-final总结 本想在知乎上发起一个话题:没有半点准备实力菜得抠脚的选手突然有机会参加final是什么体验.不过感觉这样太高调了,于是..... 以上说的就是事实,毫无准备.毫无状 ...

  5. leetcode之twosum

    class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { vector& ...

  6. hdu 4091

    #include<stdio.h> #include<math.h> __int64 gcd(__int64 a,__int64 b) {  if(b==0)   return ...

  7. ubuntu使用git提交github时,执行pull或者push命令要重新输入用户名和密码

    ubuntu使用git提交github时,执行pull或者push命令要重新输入用户名和密码: 1:问题现象: hlp@hlp:~/code/github_code/catch_imooc1$ git ...

  8. linux 安装问题make: 没有指明目标并且找不到makefile。 停止

    错误发生的可能原因,忘记安装软件需要的依赖.

  9. python学习之 - 时间模块

    时间模块模块名:time时间模块的转换流程图. UTC:英国格林威治时间.时间戳作用:是用来进行时间计算的.进行加减时间.注意:时间计算是用秒为单位time.process_time():测量处理器运 ...

  10. 洛谷——P2916 [USACO08NOV]为母牛欢呼Cheering up the Cows

    https://www.luogu.org/problem/show?pid=2916 题目描述 Farmer John has grown so lazy that he no longer wan ...