题目链接:点击查看

题目大意:给出一个由 n 个数位组成的数字,现在可以通过将其不同的后缀移到前面来组成 n 个新的数字,现在要求出 n 个新数字进行去重后,有多少个新数字分别大于、等于、小于原数字

如:1234进行上述转移可以得到的四个新数字分别为:1234,4123,3412,2341

题目分析:如果暴力的比较虽然看似只需要枚举 n 个新的字符串,但是每个字符串的比较还需要花费O(n)的时间,这样一来一去时间复杂度就到了n*n,我们必须想办法优化,因为每次比较的答案是后缀和前缀拼接而成的,这不难想到用扩展KMP求出extend数组,这样就能得到每个后缀与原字符串的最长公共前缀了,如果最长公共前缀的所有数字都是相同的,那么我们只需要比较接下来不相同的一位就可以直接得到其大小关系了,因为是后缀拼接到前缀所得到的答案,我们可以将原串复制一遍拼接到他后面,对于这个两倍长度的新串直接跑扩展KMP,如果最长公共前缀的长度大于等于原字符串的长度的话,就说明当前的后缀拼到前缀去是与原数字相同的,其他情况就可以直接比较失配的那一位的大小了,至于去重,我们可以一开始对于原串跑出KMP的next数组,利用循环串的性质去重就好了

有个小细节就是扩展KMP的数组记得开两倍大小,不然会一直TLE

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=2e5+100; //字符串长度最大值int Next[N],extend[N],nx[N];char s[N<<1];//预处理计算Next数组
void getNext(char str[])
{int i=0,j,po,len=strlen(str);Next[0]=len; //初始化Next[0]while(str[i]==str[i+1] && i+1<len) i++; Next[1]=i; //计算Next[1]po=1; //初始化po的位置for(i=2;i<len;i++){if(Next[i-po]+i < Next[po]+po) //第一种情况,可以直接得到Next[i]的值Next[i]=Next[i-po];else //第二种情况,要继续匹配才能得到Next[i]的值{j = Next[po]+po-i;if(j<0) j=0; //如果i>po+Next[po],则要从头开始匹配while(i+j<len && str[j]==str[j+i]) j++; Next[i]=j;po=i; //更新po的位置}}
}//计算extend数组
void EXKMP(char s1[],char s2[])
{int i=0,j,po,len=strlen(s1),l2=strlen(s2);getNext(s2); //计算子串的Next数组while(s1[i]==s2[i] && i<l2 && i<len) i++; extend[0]=i;po=0; //初始化po的位置for(i=1;i<len;i++){if(Next[i-po]+i < extend[po]+po) //第一种情况,直接可以得到extend[i]的值extend[i]=Next[i-po];else //第二种情况,要继续匹配才能得到extend[i]的值{j = extend[po]+po-i;if(j<0) j=0; //如果i>extend[po]+po则要从头开始匹配while(i+j<len && j<l2 && s1[j+i]==s2[j]) j++; extend[i]=j;po=i; //更新po的位置}}
}void get_next()
{int len=strlen(s);nx[0]=-1;int i=0,j=-1;while(i<len){if(j==-1||s[i]==s[j])nx[++i]=++j;elsej=nx[j];}
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int w;cin>>w;int kase=0;while(w--){scanf("%s",s);get_next(); int len=strlen(s);int t=1;if(len%(len-nx[len])==0)t=len/(len-nx[len]);for(int i=0;i<len;i++)s[i+len]=s[i];getNext(s);EXKMP(s,s);int ans1=0,ans2=0,ans3=0;for(int i=0;i<len;i++){if(extend[i]>=len)ans2++;else if(s[i+extend[i]]>s[extend[i]])ans3++;else if(s[i+extend[i]]<s[extend[i]])ans1++;}printf("Case %d: %d %d %d\n",++kase,ans1/t,ans2/t,ans3/t);}return 0;
}

HDU - 4333 Revolving Digits(扩展KMP)相关推荐

  1. HDU - 4333 Revolving Digits 拓展KMP

    传送门:点击打开链接 一个长度为lent的串T最多可以构造出lent个数字,所以这道题目的难点在于如何快速的将构造出的数字和原数字进行比较. 将两个T串合并成一个大的S串,构造出的数字实际上就是S的每 ...

  2. hdu 4333 Revolving Digits

    http://acm.hdu.edu.cn/showproblem.php?pid=4333 对我来说这个题 太难了  看着标准程序敲的  伤不起呀 解析说是和KMP有关 不过已经变形的不成样子了 如 ...

  3. 【HDOJ】4333 Revolving Digits

    扩展KMP基础题目. 1 /* 4333 */ 2 #include <iostream> 3 #include <sstream> 4 #include <string ...

  4. HDU - 6629 string matching(扩展KMP)

    题目链接:点击查看 题目大意:给出一个字符串 s 和一个暴力程序,用于求解 s 的每个后缀和原字符串的最长公共前缀,现在问一共需要执行多少次比较操作 题目分析:首先肯定不能暴力去模拟,时间复杂度n*n ...

  5. HDU 3613 Best Reward 扩展kmp算法(将一个字符串分成两个回文串)

    题目链接:https://vjudge.net/problem/HDU-3613 After an uphill battle, General Li won a great victory. Now ...

  6. 一些扩展kmp的总结

    花了一天多时间学了下ex_kmp.... 可以看刘雅琼的ppt,讲的非常清楚: 下载地址:http://url.cn/Rvjxa9 ex_kmp可以在线性时间内求文本串的每个位置与模板串的最大公共前缀 ...

  7. 【hdu 4333】Revolving Digits

    [链接]http://acm.hdu.edu.cn/showproblem.php?pid=4333 [题意] 就是给你一个数字,然后把最后一个数字放到最前面去,经过几次变换后又回到原数字,问在这些数 ...

  8. 扩展KMP --- HDU 3613 Best Reward

    Best Reward Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=3613 Mean: 给你一个字符串,每个字符都有一个权 ...

  9. HDU 3613 Best Reward 正反两次扩展KMP

    题目来源:HDU 3613 Best Reward 题意:每一个字母相应一个权值 将给你的字符串分成两部分 假设一部分是回文 这部分的值就是每一个字母的权值之和 求一种分法使得2部分的和最大 思路:考 ...

最新文章

  1. python3:利用SMTP协议发送QQ邮件+附件
  2. CCNA的全套标准实验
  3. CentOS服务器iptables配置
  4. STM32F1笔记(九)通用定时器
  5. C++ cout格式化输出
  6. eslint不报错 vue_2-2【微信小程序全栈开发课程】index页面搭建--ESlint格式错误
  7. linux双向重定向之tee命令
  8. Atitit js es5 es6新特性 attilax总结
  9. docker安装jdk1.8
  10. arcgis注册dsoframer.ocx等组件
  11. mysql用source恢复数据库_mysql source 还原数据库
  12. 根据给出的关系矩阵,判断该关系所具有的特性
  13. Unity3D IAP Google支付
  14. 旅行商问题(TSP)
  15. 1.2.2 网络抓包工具之:Fiddler
  16. (翻译)活动日历(Event Calendar)
  17. java的switch_Java中Switch用法代码示例
  18. 剑指Offer——毕业生求职网站汇总(干货)
  19. 高德地图点击按钮,控制高德地图上的热力图显示与隐藏
  20. 计算机开题报告研究方向是指,计算机开题报告导师评语

热门文章

  1. Docker Client(Docker 客户端)
  2. 请解释各种自动装配模式的区别?
  3. Spring AOP 源码分析-寻找入口
  4. spring FactoryBean的知识应用和Beanfactory的区别
  5. 微服务发现组件Eureka:简介以及Eureka服务端开发
  6. 数据库-优化-MYSQL数据库设计原则
  7. 新版本springboot-整合mybatis
  8. Condition - Java多线程编程
  9. Spring Security OAuth2源码解析(二)
  10. JVM-垃圾收集器与内存分配策略