最小(大)表示法习题 -- 来自[kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher
2016-02-22 08:43
471 查看
习题地址:
http://vjudge.net/contest/70325#overview
o.
题意:每组一个字符串,eof结束。求最小和最大表示法的位置,以及最小最大串出现的次数
做法:先求出最小位置和最大位置。最大位置只需增加代码当s[(i +k)%n] >
s[(j +k)%n].j发生变化。反之i变化即可。第二步获得nexta数组。得到最小循环串n-nexta
判断该字符串是否是周期的,如果是周期的,最小和最大的位置就是周期出现的次数
题意:每组数据n个0,1字符串。判断这些是由几种字符串第一个字符移动到最后的位置构成的
做法:求出每一个字符串的最小表示法,判断不同的字符串有几个
http://vjudge.net/contest/70325#overview
o.
题意:每组一个字符串,eof结束。求最小和最大表示法的位置,以及最小最大串出现的次数
做法:先求出最小位置和最大位置。最大位置只需增加代码当s[(i +k)%n] >
s[(j +k)%n].j发生变化。反之i变化即可。第二步获得nexta数组。得到最小循环串n-nexta
判断该字符串是否是周期的,如果是周期的,最小和最大的位置就是周期出现的次数
#include <iostream> #include <cstdio> #include <cstring> #include <string> using namespace std; int nexta[1000002]; char s[1000002]; int n; void getnexta() { memset(nexta,0,sizeof(nexta)); int k = -1,j = 0; nexta[0] = -1; while(j < n ) { if(k == -1 || s[k] == s[j]) { nexta[j + 1] = k + 1; j ++; k ++; } else { k = nexta[k]; } } } int minandmax(int x) { int i = 0,j = 1,k = 0; int t; while(i < n && j < n && k < n) { t = s[(i + k) % n] - s[(j + k) %n]; if(t == 0) { k ++; } else { if(x == 0) { if(t > 0) { i = i + k + 1; } else { j = j + k + 1; } } else { if(t < 0) { i = i + k + 1; } else { j = j + k + 1; } } if(i == j) { j ++; } k = 0; } } return min(i,j); } int main() { //freopen("in.txt","r",stdin); int maxx,minx,ans; while(scanf("%s",s) != EOF) { n = strlen(s); getnexta(); minx = minandmax(0) + 1; maxx = minandmax(1) + 1; if(n % (n -nexta ) == 0) { ans = n / (n -nexta ); } else ans = 1; printf("%d %d %d %d\n",minx,ans,maxx,ans); } return 0; } //bcabcabca bca bca bcap.
题意:每组数据n个0,1字符串。判断这些是由几种字符串第一个字符移动到最后的位置构成的
做法:求出每一个字符串的最小表示法,判断不同的字符串有几个
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <map> using namespace std; map<string,int>mapp; char s[102],t[102]; int n; int getmin() { int i = 0,j = 1,k = 0; int t; while(i < n && j < n && k < n) { t = s[(i + k) % n] - s[(j + k) %n]; if(t == 0) { k ++; } else { if(t > 0) { i = i + k + 1; } else { j = j + k + 1; } if(i == j) { j ++; } k = 0; } } return min(i,j); } int main() { //freopen("in.txt","r",stdin); int m,a,ans; string p; while(scanf("%d",&m)!= EOF) { mapp.clear(); for(int i = 0; i < m; i ++) { scanf("%s",s); n = strlen(s); a = getmin(); for(int j = 0; j < n; j ++) { t[j] = s[(a + j) % n]; } t = '\0'; p = t; mapp[p] ++; } ans = mapp.size(); printf("%d\n",ans); } return 0; }
相关文章推荐
- 利用for语句 + switch语句进行中奖判断和循环
- 查询两个日期(时间)以内的数据,between and 或 and 连>= <=,to_date()
- 安装用户脚本基本步骤
- Wireshark抓包实例分析HTTP问题
- 关于cookie和session的知识
- 大数据Lambda架构
- 大数据Lambda架构
- Mysql limit 优化,百万至千万级快速分页 复合索引的引用并应用于轻量级框架
- 判断是否第一次进入系统
- iOS横屏问题
- 数据结构之链表
- Oracle NULLIF函数
- [JAVA] java程序性能优化
- 关于c++primer的一个代码错误
- 周日的一天
- 《MVC + EF+ WCF 》——批量删除数据
- 周六加班
- EA的使用
- CocoaPods安装和使用教程
- 利用while语句 + if语句输出1~100能被3整除的数字