[BZOJ2534] L-gap字符串

Posted mangoyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ2534] L-gap字符串相关的知识,希望对你有一定的参考价值。

Description

有一种形如uvu形式的字符串,其中u是非空字符串,且V的长度正好为L,那么称这个字符串为L-Gap字符串 
给出一个字符串S,以及一个正整数L,问S中有多少个L-Gap子串. 

 

Input

第一行一个数字L 
第二行一个字符串S 

 

Output

一个数字表示S中有多少个L-Gap子串. 

 

Sample Input

3
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;
}
萌萌哒的代码>.<

 









以上是关于[BZOJ2534] L-gap字符串的主要内容,如果未能解决你的问题,请参考以下文章

UVA10829 L-Gap Substrings

[bzoj1966][Ahoi2005][VIRUS 病毒检测] (字符串dp)

[BZOJ1072][SCOI2007]排列perm

bzoj2434阿狸的自动机

Bzoj2339--Hnoi2011卡农

HDU 2534 Score