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