最短假子串

Posted powerofchoas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最短假子串相关的知识,希望对你有一定的参考价值。

给定一个 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 }

 

以上是关于最短假子串的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4032: [HEOI2015]最短不公共子串(LibreOJ #2123)

bzoj4032: [HEOI2015]最短不公共子串

A 和 B 的计数差异最大的最短子串

java 最短回文子串

最短的包含字符串 (尺取)

51nod 1127 最短的包含字符串