博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
hdu4333
阅读量:6229 次
发布时间:2019-06-21

本文共 1717 字,大约阅读时间需要 5 分钟。

题意

给出一个长度为 \(n\) 的数字,每次可以将最后一位放到前面,那么一共会有 \(n\) 个数字,问有几个不同的数字比原来的数字大,小或相等。

分析

将字符串扩展到原来的两倍,然后求一发 EXKMP ,得到 \(nxt\) 数组表示后缀串与整个串的最长公共前缀长度,那么要么有下个一个字符不同,或者全部相同,对于后者判断是否产生了循环节,对于前者直接比较大小即可。

注意求的是有几个不同的数字,所以一旦发现存在最小长度的循环节后就要退出循环。

code

#include 
using namespace std;// 调用前// nxt[0] = 0;// exkmp(s2 + 1, s2, nxt + 1, nxt); // s2 作为模板串// exkmp(s1, s2, ex, nxt);// O(n+m)的复杂度下求出字符串s1的任意后缀与字符串s2的最长公共前缀// nxt[i]==j 表示s2的以s2[i]为起始的后缀与串本身的最长公共前缀长度j// ex[i]为s1[i..]与s2的最长公共前缀,nxt[i]为s2[i..]与s2的最长公共前缀void exkmp(char s1[], char s2[], int ex[], int nxt[]) { int i = 0, j = 0, p = -1; while(s1[i]) { if(p == -1) { j = 0; do p++; while(s1[i + p] && s1[i + p] == s2[j + p]); ex[i] = p; } else if(nxt[j] != p) ex[i] = min(p, nxt[j]); else { j = 0; while(s1[i + p] && s1[i + p] == s2[j + p]) p++; ex[i] = p; } i++; j++; p--; } ex[i] = 0;}const int MAXN = 2e5 + 10;char s[MAXN];int nxt[MAXN];int main() { int T; scanf("%d", &T); for(int kase = 1; kase <= T; kase++) { nxt[0] = 0; scanf("%s", s); int len = strlen(s); for(int i = len; i < 2 * len; i++) s[i] = s[i - len]; s[2 * len] = 0; exkmp(s + 1, s, nxt + 1, nxt); int L = 0, G = 0; for(int i = 1; i < len; i++) { int x = nxt[i]; if(min(x, len - i) + i == len && len % i == 0) { // 说明存在循环节,那么后面都是重复的 break; } if(x < len) { if(s[x] < s[i + x]) G++; else L++; } } printf("Case %d: %d 1 %d\n", kase, L, G); } return 0;}

转载于:https://www.cnblogs.com/ftae/p/7425679.html

你可能感兴趣的文章
ibatis运行的SQL语句的输出——通过配置log4j
查看>>
maven常见问题问答(超全面)
查看>>
JSP中获取各种路径的方法
查看>>
linux 特殊权限 之 SUID 实例
查看>>
linux操作命令
查看>>
Capture Nx
查看>>
RedHat/CentOS命令记录
查看>>
git 学习
查看>>
MySQL基于LVM快照的备份恢复
查看>>
庞升东:个人网站年广告销售收入可超千万
查看>>
[译]ECMAScript 5 Objects and Properties
查看>>
MPEG-7 视觉描述符
查看>>
ELK6.5 Nginx 日志搜集-05 filebeat 安装
查看>>
如何用 Retrofit 2 在安卓上实现 HTTP 访问?
查看>>
2013 北京 QCon热点分享
查看>>
Linux系统下利用文件创建文件系统
查看>>
阿轶来了~
查看>>
kickstart为root用户设置自定义密码
查看>>
tail命令
查看>>
列表运用和copy详解
查看>>