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. js总结(三):面向对象,prototype ,oo模拟

    http://aralejs.org/class/docs/competitors.html http://javascript.crockford.com/prototypal.html proto ...

  2. notepad++编辑器写python需注意使用utf-8编码

    语言:python3.4 文本编辑器:notepad++ 报错:SyntaxError: (unicode error) 'utf-8' codec can't decode byte 0xb4 in ...

  3. Ext.js双击事件

    /** * 联系人列表panel */ Ext.define('Op.OpBill.OpBillCustLinkGridPanel', { extend: 'Ext.grid.Panel', id: ...

  4. String字符串去掉双引号

    public static String stringReplace(String str) { //去掉" "号 String str= str.replace("\& ...

  5. JS获取所有LI中第三个<SPAN>

  6. 五、PL/SQL循环、游标、函数和过程

    --PL/SQL基础知识学习 --一.PL/SQL语句块,基础语法格式 DECLARE --变量声明列表 info varchar(25); --变量声明 stu_unm integer := 15; ...

  7. 洛谷P4219 - [BJOI2014]大融合

    Portal Description 初始有\(n(n\leq10^5)\)个孤立的点,进行\(Q(Q\leq10^5)\)次操作: 连接边\((u,v)\),保证\(u,v\)不连通. 询问有多少条 ...

  8. 矩形周长(codevs 2149)

    题目描述 Description N(N<5000) 张矩形的海报,照片和其他同样形状的图片贴在墙上.它们的边都是垂直的或水平的.每个矩形可以部分或者全部覆盖其他矩形.所有的矩形组成的集合的轮廓 ...

  9. Java面试题总结之Java基础(三)

    1.JAVA 语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try 块中可以抛出异常吗? 答:Java 通过面向对象的方法进行异常处理, ...

  10. Java日志框架使用技巧收集(slf4j、jcl、jul、log4j1、log4j2、logback)

    乒乓狂魔-教程: jdk-logging.log4j.logback日志介绍及原理 commons-logging与jdk-logging.log4j1.log4j2.logback的集成原理 slf ...