http://acm.hdu.edu.cn/showproblem.php?pid=4333

【题意】

  • 给定一个数字<=10^100000,每次将该数的第一位放到放到最后一位,求所有组成的不同的数比原数小的个数,相等的个数,大的个数

【思路】

  • 这个数很大,用字符串处理
  • 比较两个字符串的大小,一位一位很耗时,可以求出最长公共前缀,只比较最长公共前缀后一位
  • 每次将数的最后一位放到最后一位,如abcd变成dabc,cdab,bcda,相当于abcdabcd各个后缀的前四位
  • 这样就变成了求abcdabcd的每个后缀与abcd的最长公共前缀,用扩展KMP线性求
  • abab这种情况按上面的做法abababab会考察ab,ba,ab,ba,有重复的,是因为abab=(ab)^2,所以还要考虑最小循环节去重

【AC】

 #include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e5+;
char s[maxn];
char t[maxn];
int nxt[maxn];
int extend[maxn];
int nxtval[maxn]; void pre_EKMP(char x[],int m,int nxt[])
{
nxt[]=m;
int j=;
while(j+<m && x[j]==x[j+]) j++;
nxt[]=j;
int k=;
for(int i=;i<m;i++)
{
int p=nxt[k]+k-;
int L=nxt[i-k];
if(i+L<p+) nxt[i]=L;
else
{
j=max(,p-i+);
while(i+j<m && x[i+j]==x[j]) j++;
nxt[i]=j;
k=i;
}
}
} void EKMP(char x[],int m,char y[],int n,int nxt[],int extend[])
{
pre_EKMP(x,m,nxt);//子串
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=nxt[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;
}
}
} void kmp_pre(char x[],int m,int nxtval[])
{
int i,j;
j=nxtval[]=-;
i=;
while(i<m)
{
if(j==-||x[i]==x[j])
{
i++;
j++;
if(x[i]!=x[j]) nxtval[i]=j;
else nxtval[i]=nxtval[j];
}
else j=nxtval[j];
} } void NextVal(char *T)
{
int i=,j=-;
nxtval[]=-;
int Tlen=strlen(T);
while(i<Tlen)
{
if(j==-||T[i]==T[j])
{
i++;
j++;
if(T[i]!=T[j]) nxtval[i]=j;
else nxtval[i]=nxtval[j];
}
else j=nxtval[j];
}
} int main()
{
int T;
scanf("%d",&T);
int cas=;
while(T--)
{
scanf("%s",s);
strcpy(t,s);
strcat(s,t);
int a,b,c;
a=b=c=;
int ls=strlen(s);
int lt=strlen(t);
EKMP(t,lt,s,ls,nxt,extend);
kmp_pre(t,lt,nxtval);
int p=lt-nxtval[lt];
int tmp=;
if(lt%p==) tmp=lt/p;
for(int i=;i<lt;i++)
{
if(extend[i]==lt) a++;
else if(s[i+extend[i]]>t[extend[i]]) c++;
else b++;
}
printf("Case %d: %d %d %d\n",++cas,b/tmp,a/tmp,c/tmp);
}
return ;
}

扩展kmp求最小循环节方法一:kmp预处理

扩展kmp计算最小循环节方法二:利用已知的next数组

【知识点】

扩展kmp的next数组与kmp数组的next含义不同,是字符串s的所有后缀和s本身的最长公共前缀

【坑点】

做这道题踩了各种坑

  • strcat函数的用法:strcat(s,s)是错误的,会T,strcat的两个参数传的是指针,就是s在内存里面的位置,这里两个s是同一个东西 第一个s变长的时候,第二个s也会变长,然后就没完没了了
  •  

【扩展kmp+最小循环节】HDU 4333 Revolving Digits的更多相关文章

  1. HDU 4333 Revolving Digits 扩张KMP

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

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

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

  3. 扩展KMP - HDU 4333 Revolving Digits

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

  4. hdu 3746 Cyclic Nacklace(kmp最小循环节)

    Problem Description CC always becomes very depressed at the end of this month, he has checked his cr ...

  5. HDU 6740 kmp最小循环节

    题意:给一个无线循环小数的前几位,给n,m 选择其中一种出现在前几位的循环节方式(a个数),循环节的长度b 使得n*a-m*b最大 样例: 2 1 12.1212 输出 6 选择2,2*1-1*1=1 ...

  6. hdu3746(kmp最小循环节)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3746 题意:问在一个字符串末尾加上多少个字符能使得这的字符串首尾相连后能够循环 题解:就是利用next ...

  7. Cyclic Nacklace hdu3746 kmp 最小循环节

    题意:给出一段字符串  求最少在最右边补上多少个字符使得形成循环串(单个字符不是循环串) 自己乱搞居然搞出来了... 想法是:  如果nex[len]为0  那么答案显然是补len 否则  答案为循环 ...

  8. HDU1358 Period —— KMP 最小循环节

    题目链接:https://vjudge.net/problem/HDU-1358 Period Time Limit: 2000/1000 MS (Java/Others)    Memory Lim ...

  9. HDU3746 Cyclic Nacklace —— KMP 最小循环节

    题目链接:https://vjudge.net/problem/HDU-3746 Cyclic Nacklace Time Limit: 2000/1000 MS (Java/Others)    M ...

随机推荐

  1. Android的Activity之间传对象的方法

    传值代码块 //Serializeable传递对象的方法 public void SerializeMethod(){ Person mPerson = new Person(); mPerson.s ...

  2. MAC 安装汇编编译工具 NASM

    直接运行nasm报错: 开始安装: brew reinstall nasm

  3. mac系统下android studio创建手机模拟器

    打开android studio,点击右上角的模拟器图标,打开“Android Virtual Device Manager” 窗口,如下图   点击“Create Virtual Device”,在 ...

  4. scanf函数详解

    函数名: scanf 功 能: 执行格式化输入 用 法: int scanf(char *format[,argument,...]);scanf()函数是通用终端格式化输入函数,它从标准输入设备(键 ...

  5. 八 个优秀的 jQuery Mobile 教程

    jQuery Mobile 是 jQuery 在手机上和平板设备上的版本.jQuery Mobile不仅会给主流移动平台带来jQuery核心库,而且会发布一个完整统一的jQuery移动UI框架.虽然j ...

  6. nodejs 设置安装包路径的取消和安装cnpm

    安装cnpm: $ npm install -g cnpm --registry=https://registry.npm.taobao.org 配置nodejs的npm安装包路径: npm conf ...

  7. xadmin下设置“use_bootswatch = True”无效的解决办法

    环境: python 2.7 django 1.9 xadmin采用源代码的方式引入到项目中 问题: 在xadmin使用的过程中,设置“use_bootswatch = True”,企图调出主题菜单, ...

  8. 【Git版本控制】Git使用教程

    1.Git的综述 SVN是集中式版本控制系统,版本库集中放在中央服务器上,而干活时用的都是自己的电脑,所以首先要从中央服务器哪里得到最新的版本,然后干活,干完后,需要把自己做完的活推送到中央服务器.集 ...

  9. 【Python学习之二】装饰器

    装饰器 首先,给出装饰器的框架: def log(func): def wrapper(*args, **kw): print('call %s():' % func.__name__) return ...

  10. 【java】【转发】classpath、path、JAVA_HOME的作用及JAVA环境变量配置

    CLASSPATH是什么?它的作用是什么? 它是javac编译器的一个环境变量.它的作用与import.package关键字有关.当你写下improt java.util.*时,编译器面对import ...