后缀数组 hihocoder 1084 Extend KMP

注意到k <= 5

#include <iostream>
#include <queue> 
#include <stack> 
#include <map> 
#include <set> 
#include <bitset> 
#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 200005
#define maxm 2000005
#define eps 1e-10
#define mod 1000000007
#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
// head

char s[maxn];  
int sa[maxn], c[maxn], t1[maxn], t2[maxn];  
int rank[maxn], height[maxn];  
void build(int n, int m)  
{  
    int *x = t1, *y = t2, p;  
    for(int i = 0; i < m; i++) c[i] = 0;  
    for(int i = 0; i < n; i++) c[x[i] = s[i]]++;  
    for(int i = 1; i < m; i++) c[i] += c[i-1];  
    for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;  
    for(int k = 1; k <= n; k <<= 1) {  
        p = 0;  
        for(int i = n-k; i < n; i++) y[p++] = i;  
        for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;  
        for(int i = 0; i < m; i++) c[i] = 0;  
        for(int i = 0; i < n; i++) c[x[y[i]]]++;  
        for(int i = 1; i < m; i++) c[i] += c[i-1];  
        for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];  
        p = 1, swap(x, y), x[sa[0]] = 0;  
        for(int i = 1; i < n; i++)  
            x[sa[i]] = y[sa[i]] == y[sa[i-1]] && y[sa[i] + k] == y[sa[i-1] + k] ? p-1 : p++;  
        if(p >= n) break;  
        m = p;  
    }  
}  
void getheight(int n)  
{  
    int k = 0;  
    for(int i = 0; i <= n; i++) rank[sa[i]] = i;  
    for(int i = 0; i < n; i++) {  
        if(k) k--;  
        int j = sa[rank[i] - 1];  
        while(s[i + k] == s[j + k]) k++;  
        height[rank[i]] = k;  
    }  
}  
  
int p[maxn];  
int st1[maxn][20];  
int sum[maxn];  
void init(int n, int *a, int (*t)[20])  
{  
    p[0] = -1;  
    for(int i = 1; i <= n; i++) p[i] = i & (i-1) ? p[i-1] : p[i-1] + 1;  
    for(int i = 1; i <= n; i++) t[i][0] = a[i];  
    for(int j = 1; j <= p[n]; j++)  
        for(int i = 1; i + (1 << j) - 1 <= n; i++)  
            t[i][j] = min(t[i][j-1], t[i + (1 << (j-1))][j-1]);  
}  
int query(int l, int r, int (*t)[20])  
{  
    int k = p[r - l + 1];  
    return min(t[l][k], t[r - (1 << k) + 1][k]);  
}  
int lcp(int a, int b)  
{  
    if(a > b) swap(a, b);  
    return query(a+1, b, st1);  
}  

char pp[maxn];
int k;

void read(void)
{
	scanf("%s", pp);
	scanf("%d", &k);
}

void work(void)
{
	int len = strlen(s);
	int t = strlen(pp);
	s[len] = 'A';
	for(int i = len+1; i <= len + t; i++) s[i] = pp[i - len - 1];
	int n = len;
	s[len + t + 1] = '\0';
	len = len + t + 1;
	
	build(len + 1, 128);
	getheight(len);
	init(len, height, st1);
	int ans = 0;	

	//for(int i = 0; i < len; i++) printf("AA %d \n", lcp(rank[0], rank[8]));

	int tmp;
	for(int i = 0; i <= n - t; i++) {
		int j = n + 1, cnt = 0, now = i;
		tmp = 0;
		while(cnt <= k) {
			tmp = lcp(rank[now], rank[j]);
			now += tmp;
			j += tmp;
			if(j - n - 1 >= t) {
				ans++;
				break;
			}
			now++, j++;
			cnt++;
		}
		//if(tmp && cnt == k+1) ans++;
		//if(cnt <= k) ans++;

	}
	printf("%d\n", ans);
}

int main(void)
{
	while(scanf("%s", s)!=EOF) {
		read();
		work();
	}	


	return 0;
}


你可能感兴趣的:(hihoCoder)