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】

  1. #include<iostream>
  2. #include<cstring>
  3. #include<string>
  4. #include<cstdio>
  5. #include<algorithm>
  6. using namespace std;
  7. typedef long long ll;
  8. const int maxn=2e5+;
  9. char s[maxn];
  10. char t[maxn];
  11. int nxt[maxn];
  12. int extend[maxn];
  13. int nxtval[maxn];
  14.  
  15. void pre_EKMP(char x[],int m,int nxt[])
  16. {
  17. nxt[]=m;
  18. int j=;
  19. while(j+<m && x[j]==x[j+]) j++;
  20. nxt[]=j;
  21. int k=;
  22. for(int i=;i<m;i++)
  23. {
  24. int p=nxt[k]+k-;
  25. int L=nxt[i-k];
  26. if(i+L<p+) nxt[i]=L;
  27. else
  28. {
  29. j=max(,p-i+);
  30. while(i+j<m && x[i+j]==x[j]) j++;
  31. nxt[i]=j;
  32. k=i;
  33. }
  34. }
  35. }
  36.  
  37. void EKMP(char x[],int m,char y[],int n,int nxt[],int extend[])
  38. {
  39. pre_EKMP(x,m,nxt);//子串
  40. int j=;
  41. while(j<n && j<m &&x[j]==y[j]) j++;
  42. extend[]=j;
  43. int k=;
  44. for(int i=;i<n;i++)
  45. {
  46. int p=extend[k]+k-;
  47. int L=nxt[i-k];
  48. if(i+L<p+) extend[i]=L;
  49. else
  50. {
  51. j=max(,p-i+);
  52. while(i+j<n && j<m && y[i+j]==x[j]) j++;
  53. extend[i]=j;
  54. k=i;
  55. }
  56. }
  57. }
  58.  
  59. void kmp_pre(char x[],int m,int nxtval[])
  60. {
  61. int i,j;
  62. j=nxtval[]=-;
  63. i=;
  64. while(i<m)
  65. {
  66. if(j==-||x[i]==x[j])
  67. {
  68. i++;
  69. j++;
  70. if(x[i]!=x[j]) nxtval[i]=j;
  71. else nxtval[i]=nxtval[j];
  72. }
  73. else j=nxtval[j];
  74. }
  75.  
  76. }
  77.  
  78. void NextVal(char *T)
  79. {
  80. int i=,j=-;
  81. nxtval[]=-;
  82. int Tlen=strlen(T);
  83. while(i<Tlen)
  84. {
  85. if(j==-||T[i]==T[j])
  86. {
  87. i++;
  88. j++;
  89. if(T[i]!=T[j]) nxtval[i]=j;
  90. else nxtval[i]=nxtval[j];
  91. }
  92. else j=nxtval[j];
  93. }
  94. }
  95.  
  96. int main()
  97. {
  98. int T;
  99. scanf("%d",&T);
  100. int cas=;
  101. while(T--)
  102. {
  103. scanf("%s",s);
  104. strcpy(t,s);
  105. strcat(s,t);
  106. int a,b,c;
  107. a=b=c=;
  108. int ls=strlen(s);
  109. int lt=strlen(t);
  110. EKMP(t,lt,s,ls,nxt,extend);
  111. kmp_pre(t,lt,nxtval);
  112. int p=lt-nxtval[lt];
  113. int tmp=;
  114. if(lt%p==) tmp=lt/p;
  115. for(int i=;i<lt;i++)
  116. {
  117. if(extend[i]==lt) a++;
  118. else if(s[i+extend[i]]>t[extend[i]]) c++;
  119. else b++;
  120. }
  121. printf("Case %d: %d %d %d\n",++cas,b/tmp,a/tmp,c/tmp);
  122. }
  123. return ;
  124. }

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

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

【知识点】

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

【坑点】

做这道题踩了各种坑

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

【扩展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. vue+element ui项目总结点(三)富文本编辑器 vue-wangeditor

    1.参考 https://www.npmjs.com/package/vue-wangeditor 使用该富文本编辑器 <template> <div class="egi ...

  2. Django 表增加外键

    1.创建临时表,并把原表的数据复制到临时表 先根据python manage syl article查看创建临时表 CREATE TABLE `article_article_temp` ( `id` ...

  3. python实现微信打飞机游戏(by crossin)

    # -*- coding: utf-8 -*- import pygame from sys import exit import random pygame.init() screen = pyga ...

  4. Codeforces Round #317 div2 E div1 C CNF 2 (图论,匹配)

      CNF 2 'In Boolean logic, a formula is in conjunctive normal form (CNF) or clausal normal form if i ...

  5. 前端css学习记录

    参考资料:CSS权威指南(第三版)中文版 核心要点: HTML负责标记文档的结构(HyperText Markup Language),结构化语言. CSS 负责表现文档的样式(Cascading S ...

  6. 《嵌入式linux应用程序开发标准教程》笔记——6.文件IO编程

    前段时间看APUE,确实比较详细,不过过于详细了,当成工具书倒是比较合适,还是读一读这种培训机构的书籍,进度会比较快,遇到问题时再回去翻翻APUE,这样的效率可能更高一些. <嵌入式linux应 ...

  7. Flask扩展实现HTTP令牌token认证HTTPTokenAuth

    Token认证 在restful设计中,用户认证模式通常使用json web token,而不会使用传统的HTTP Basic认证(传入账号密码) token认证模式如下:在请求header中加入to ...

  8. python 学习总结4

    数字类型及操作 一.整数类型 (1)python中的整数与数学中的概念是一致的,可以正也可以负,没有取值范围.   pow(x,y)函数是计算x的y次幂,想计算多大就多大. (2)在整数类型中有四种进 ...

  9. initcall机制

    参考:initcall机制 /* include/linux/init.h: */ /* For assembly routines */ #define __HEAD .section " ...

  10. Lex与Yacc学习(二)之第一个Lex程序

    用lex识别单词 构建一个识别不同类型英语单词的简单程序.先识别词性(名词,动词等),然后再扩展到处理符合简单英语语法的多个单词的句子. 先列出要识别的一组动词: is    am   are   w ...