鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 编程语言开发 > c++ > >

最短假子串

来源:互联网 作者:佚名 时间:2018-01-25 11:28
给定一个 01 串 s,请你找到一个最短的非空串 t?,使得 t 不是 s 的子串。 其中 |s| 表示 s 的长度。 输出一行最短的不是输入串子串的非空串的长度。 思路: 最长假子串的长度不大于log|s|。 转换思路,只需枚举小于等于log|s|的子串t,判断s中是否已经出现

给定一个 01 串 s,请你找到一个最短的非空串 t?,使得 t 不是 s 的子串。

其中 |s| 表示 s 的长度。

输出一行最短的不是输入串子串的非空串的长度。

思路:

最长假子串的长度不大于log|s|。转换思路,只需枚举小于等于log|s|的子串t,判断s中是否已经出现所有该长度的子串,即不同t的总数是否等于2^(|t|),若有该长度的子串未在s中出现,则为答案。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 #define MAXN (4500000 + 10)
 5 char s[MAXN];
 6 int vis[MAXN];
 7 int k, cur, ans;
 8 int main() {
 9     int T;
10     scanf("%d", &T);
11     while(T--) {
12         scanf("%s", &s);
13         int len = strlen(s);
14         for(k = 1; (1 << k) <= len; k++); // 需要枚举的长度
15         ans = k;
16         
17         while(--k) {
18             int MOD = (1 << k) - 1; // 该长度子串的总数
19             int x = 0;
20             cur++;
21             
22             for(int i = 0; i < k; i++) 
23                 x = (x << 1) | (s[i] - '0'); // 枚举
24             vis[x] = cur;
25             for(int i = k; i < len; i++) {
26                 x = (x << 1) | (s[i] - '0'); // 枚举
27                 vis[x & MOD] = cur;
28             }
29             
30             bool flag = 0;
31             for(int i = 0; i < (1 << k); i++) 
32                 if(vis[i] != cur) { // 若有长度未被完全包括
33                     flag = 1;
34                     break;
35                 }
36             
37             if(flag)
38                 ans = k;
39             else
40                 break;
41         }
42         printf("%d\n", ans);
43     }
44     return 0;
45 }

 

网友评论
<