Description
有一种形如uvu形式的字符串,其中u是非空字符串,且V的长度正好为L,那么称这个字符串为L-Gap字符串
给出一个字符串S,以及一个正整数L,问S中有多少个L-Gap子串.
Input
第一行一个数字L
第二行一个字符串S
Output
一个数字表示S中有多少个L-Gap子串.
Sample Input
3
aabbaa
aabbaa
Sample Output
2
HINT
S的长度不超过50000,L<=10
解题思路:
考虑枚举u串的长度k,那么当前枚举到的L-gap串的长度就是2 * k + L,然后把整个字符串分成若干个长度为2 * k + L的块,对于每一个块算在u串能取的区间是多少,对于块中两个u串的开始下标l1, l2,可以求出包括自身的情况下向左可以移动的长度Min(前缀l1,l2的最长公共后缀, len),向右可以移动的长度Min(后缀l1,l2的最长公共前缀,len),二分+hash搞一下就可以了,如果说可以移动的总长度>= k,显然这个块就会产生 k - 总长度 + 1种u串,然后对于每一个k,所划分出的每一个块去算,总复杂度是(nlogn^2)
/*program by mangoyang*/ #include<bits/stdc++.h> #define inf (0x7f7f7f7f) #define Max(a, b) ((a) > (b) ? (a) : (b)) #define Min(a, b) ((a) < (b) ? (a) : (b)) #define N (100005) typedef long long ll; typedef unsigned long long ull; using namespace std; template <class T> inline void read(T &x){ int f = 0, ch = 0; x = 0; for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = 1; for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - ‘0‘; if(f) x = -x; } const ull base = 233; char s[N]; int n, m, ans; ull pw[N], hs[N]; inline ull get(int l, int r){ if(l > r) return 0; return hs[r] - hs[l-1] * pw[r-l+1]; } inline int getpre(int x, int y, int lim){ int l = 0, r = lim, ans = 0; while(l <= r){ int mid = l + r >> 1; if(get(x - mid + 1, x) == get(y - mid + 1, y)) ans = mid, l = mid + 1; else r = mid - 1; } return ans; } inline int getsuf(int x, int y, int lim){ int l = 0, r = lim, ans = 0; while(l <= r){ int mid = l + r >> 1; if(get(x, x + mid - 1) == get(y, y + mid - 1)) ans = mid, l = mid + 1; else r = mid - 1; } return ans; } inline void solve(int L, int R){ int len = (R - L + 1 - m) / 2, l1 = L, l2 = R - len + 1; int llen = getpre(l1, l2, len), rlen = getsuf(l1, l2, len); int now = (llen && rlen) ? llen + rlen - 1 : llen + rlen; if(now >= len) ans += now - len + 1; } int main(){ pw[0] = 1, read(m); scanf("%s", s + 1); int n = strlen(s + 1); for(int i = 1; i < N; i++) pw[i] = pw[i-1] * base; for(int i = 1; i <= n; i++) hs[i] = hs[i-1] * base + s[i]; for(int k = 1; k <= (n - m) / 2; k++) for(int i = 1; i <= n; i += k) solve(i, i + 2 * k + m - 1); cout << ans; return 0; }