算法练习——Tricky and Clever Password
2017-03-13 21:59
337 查看
问题描述
在年轻的时候,我们故事中的英雄——国王 Copa——他的私人数据并不是完全安全地隐蔽。对他来说是,这不可接受的。因此,他发明了一种密码,好记又难以破解。后来,他才知道这种密码是一个长度为奇数的回文串。
Copa 害怕忘记密码,所以他决定把密码写在一张纸上。他发现这样保存密码不安全,于是他决定按下述方法加密密码:他选定一个整数 X ,保证 X 不小于 0 ,且 2X 严格小于串长度。然后他把密码分成 3 段,最前面的 X 个字符为一段,最后面的 X 个字符为一段,剩余的字符为一段。不妨把这三段依次称之为 prefix, suffix, middle 。显然, middle 的长度为一个大于 0 的奇数,且 prefix 、suffix 的长度相等。他加密后的密码即为 A + prefix + B + middle
+ C +suffix ,其中 A 、 B 、 C 是三个由 Copa 选定的字符串,且都有可能为空, + 表示字符串相连。
许多年过去了。Copa 昨天找到了当年写下加密后字符串的那张纸。但是,Copa 把原密码、A、B、C 都忘了。现在,他请你找一个尽量长的密码,使得这个密码有可能被当年的 Copa 发明、加密并写下。
输入格式
输入包含一个只含有小写拉丁字母的字符串,长度在 1 到 10^5 之内。
输出格式
第一行包含一个整数 k ,表示你找到的原密码分成的 3 个部分中有多少个非空字符串。显然 k in {1, 3} 。接下来 k 行,每行 2 个用空格分开的整数 x_i l_i ,表示这一部分的起始位置和长度。要求输出的 x_i 递增。
起始位置 x_i 应该在 1 到加密后的字符串长度之间。 l_i 必须是正整数,因为你只要输出非空部分的信息。 middle 的长度必须为奇数。
如果有多组答案,任意一组即可。提示:你要最大化的是输出的 l_i 的总和,而不是 k 。
样例输入
abacaba
样例输出
1
1 7
样例输入
axbya
样例输出
3
1 1
2 1
5 1
样例输入
xabyczba
样例输出
3
2 2
4 1
7 2
数据规模和约定
对于 10% 的数据: n <= 10
对于 30% 的数据: n <= 100
对于 100% 的数据: n <= 100000
存在 20% 的数据,输出文件第一行为 1 。
C++代码如下:
在年轻的时候,我们故事中的英雄——国王 Copa——他的私人数据并不是完全安全地隐蔽。对他来说是,这不可接受的。因此,他发明了一种密码,好记又难以破解。后来,他才知道这种密码是一个长度为奇数的回文串。
Copa 害怕忘记密码,所以他决定把密码写在一张纸上。他发现这样保存密码不安全,于是他决定按下述方法加密密码:他选定一个整数 X ,保证 X 不小于 0 ,且 2X 严格小于串长度。然后他把密码分成 3 段,最前面的 X 个字符为一段,最后面的 X 个字符为一段,剩余的字符为一段。不妨把这三段依次称之为 prefix, suffix, middle 。显然, middle 的长度为一个大于 0 的奇数,且 prefix 、suffix 的长度相等。他加密后的密码即为 A + prefix + B + middle
+ C +suffix ,其中 A 、 B 、 C 是三个由 Copa 选定的字符串,且都有可能为空, + 表示字符串相连。
许多年过去了。Copa 昨天找到了当年写下加密后字符串的那张纸。但是,Copa 把原密码、A、B、C 都忘了。现在,他请你找一个尽量长的密码,使得这个密码有可能被当年的 Copa 发明、加密并写下。
输入格式
输入包含一个只含有小写拉丁字母的字符串,长度在 1 到 10^5 之内。
输出格式
第一行包含一个整数 k ,表示你找到的原密码分成的 3 个部分中有多少个非空字符串。显然 k in {1, 3} 。接下来 k 行,每行 2 个用空格分开的整数 x_i l_i ,表示这一部分的起始位置和长度。要求输出的 x_i 递增。
起始位置 x_i 应该在 1 到加密后的字符串长度之间。 l_i 必须是正整数,因为你只要输出非空部分的信息。 middle 的长度必须为奇数。
如果有多组答案,任意一组即可。提示:你要最大化的是输出的 l_i 的总和,而不是 k 。
样例输入
abacaba
样例输出
1
1 7
样例输入
axbya
样例输出
3
1 1
2 1
5 1
样例输入
xabyczba
样例输出
3
2 2
4 1
7 2
数据规模和约定
对于 10% 的数据: n <= 10
对于 30% 的数据: n <= 100
对于 100% 的数据: n <= 100000
存在 20% 的数据,输出文件第一行为 1 。
C++代码如下:
#include<stdio.h> #include<string.h> #define INF 0x3f3f3f3f char s[100010], s1[200010]; int mana[100010], L, next[200010],match[100010], r[100010]; int min(int x, int y) { return x<y?x:y; } void getmana() { mana[0] = 0; int i; int id = 0, right = 0; for(i = 1; i < L-1; ++i) { if(right > i) mana[i] = min(mana[2*id - i], right - i); else mana[i] = 0; while(s[i+mana[i]+1] == s[i-mana[i]-1] && (i+mana[i]+1) < L && (i-mana[i]-1) >= 0) mana[i]++; if(mana[i]+i > right) { id = i; right = mana[i]+i; } } } void getnext(char *temp) { memset(next, 0, sizeof(next)); next[0] = -1; int i = 0, j = -1; while(temp[i]) { if(j == -1 || temp[i] == temp[j]) { i++; j++; next[i] = j; } else j = next[j]; } } int main() { int i, j, k, l; while(gets(s) != NULL) { L = strlen(s); getmana(); for(i = L-1; i >= 0; --i) s1[L-1-i] = s[i]; s1[L] = '#'; s1[L+1] = '\0'; strcat(s1,s); getnext(s1); for(i = L+1; i <= 2*L+1; ++i) match[i-L-1] = next[i]; memset(r, -1, sizeof(r)); for(i = 1; i <= L; ++i) { if(match[i] > match[i-1]) r[match[i]-1] = i-1; else match[i] = match[i-1]; } for(i = 1; i < L; ++i) { if(r[i] == -1) r[i] = r[i-1]; // printf("%d ",r[i]); } // printf("\n"); int ans[3][2] = {0}, max = 0; bool ok = true; for(i = 1; i < L-1; ++i)//the lengthmust bigger than 3 { j = i+mana[i]+1; if(j >= L || i-mana[i] <= 0) j = L; else { if(r[L-j-1] == -1) j = L; else { if(r[L-j-1] >=i-mana[i]) j = L -match[i-mana[i]]; else j = L -match[r[L-j-1]+1]; } } if(j < L) { if(2*(L-j) + mana[i]*2 + 1 >max) { max = 2*(L-j) + mana[i]*2 +1; ans[0][0] = r[L-j-1] - L +j + 1; ans[0][1] = L-j; ans[1][0] = i-mana[i]; ans[1][1] =2*mana[i]+1; ans[2][0] = j; ans[2][1] = L-j; ok = false; // printf("1 %d\n",max); } } else { if(2*mana[i]+1 > max) { max = 2*mana[i]+1; ok = true; ans[1][0] = i-mana[i]; ans[1][1] =2*mana[i]+1; } } } if(ok) { if(ans[1][1] == 0) ans[1][1] = 1; printf("1\n%d %d\n", ans[1][0]+1, ans[1][1]); } else { printf("3\n"); printf("%d %d\n", ans[0][0]+1, ans[0][1]); printf("%d %d\n", ans[1][0]+1, ans[1][1]); printf("%d %d\n", ans[2][0]+1, ans[2][1]); } } return 0; }
相关文章推荐
- 算法笔记_055:蓝桥杯练习 Tricky and Clever Password (Java)
- 算法笔记_055-蓝桥杯练习 Tricky and Clever Password (Java)
- 算法笔记_055-蓝桥杯练习 Tricky and Clever Password (Java)
- 算法训练 Tricky and Clever Password
- codeforces 30E 蓝桥杯 Tricky and Clever Password
- Tricky and Clever Passwordcsnd
- Codeforces #30E: Tricky and Clever Password 题解
- 蓝桥杯-Tricky and Clever Password(java)
- Tricky and Clever Password 【KMP+Manacher】【蓝桥杯试题】
- 算法练习(37):Best Time to Buy and Sell Stock
- Python 编程练习1:login and password
- 算法练习(32):Delete and Earn
- 算法分析课每周练习 Serialize and Deserialize Binary Tree
- CF 288DIV2 D - Tanya and Password (弗罗莱算法求欧拉通路)
- 算法练习(38):Best Time to Buy and Sell Stock with Transaction Fee
- 算法练习(42):Best Time to Buy and Sell Stock II
- Tapestry学习七:关于组件(二)TextField, PasswordField and PageLink
- Designing for Interaction: Creating Smart Applications and Clever Devices
- 算法练习五:求数组中第k大的数
- 字符串的“无重复”全排列非递归算法 [小算法练习]