首页 > 代码库 > SGU 142.Keyword
SGU 142.Keyword
时间限制:0.5s
空间限制:16M
题意
给出一个仅由‘a‘,‘b’组成的字符串S,长度小于500 000,求一个由‘a’,‘b’组成的不是S子串的字符串T。
输出T的长度和T。
Sample Input
11aabaaabbbab
Sample Output
4aaaa
Solution:
从字符串长度上看,我们需要一个O(n)的算法.
考虑串T的最大长度,在什么范围
长度为k的串,有2k个,占了k*2k位,即1*2+2*2k,+....+p*2P<=500 000;
可知串T的长度是小于log2(500000)<19,的.
因此只要从S串的开始,每一位往后最多枚举19位,就能筛选出所有有用的子串.
如果用 1 0 分别代表‘a‘,‘b‘ ;
那么可以用一个二进制长为19位的数代表这个串.
只需要开一个f[length][key]的数组(length<=19,key<=219),注意到内存只有16M,因此,这个二维数组的类型必须是bool型,不然将超出内存限制.
最后从数组中找到最短的那个没有出现过的串,输出即可.
时间复杂度正是O(n),满足我们的需要的.
参考代码
#include <cstdio>#include <cmath>char ch;int g[1 << 19];bool f[20][1 << 19];int k, n, len, fid;int main() { scanf ("%d", &n); ch = getchar(); for (int i = 1; i <= n; i++) g[i] = (ch=getchar() == ‘a‘); for (int i = 1; i <= n; i++) { k = 0; for (int j = 0; j <= 18; j++) { if (i + j <= n) { k = k << 1 | g[i + j]; f[j + 1][k] = 1; } else break; } } for (len = 1; len <= 19; len++) { for (k = 0; k < (1<<len); k++) if (!f[len][k]) { fid = 1; break; } if (fid) break; } printf ("%d\n", len); for (int i = len - 1; i >= 0; i--) printf ("%c", k & (1 << i) ? ‘a‘ : ‘b‘);}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。