zoukankan      html  css  js  c++  java
  • 洛谷P3763 [Tjoi2017]DNA 【后缀数组】

    题目链接

    洛谷P3763

    题解

    后缀数组裸题
    在BZOJ被卡常到哭QAQ

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (register int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    #define res register
    using namespace std;
    const int maxn = 200005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	res int out = 0,flag = 1; res char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    char s[maxn],s2[maxn];
    int sa[maxn],rank[maxn],height[maxn],bac[maxn],t1[maxn],t2[maxn],mn[maxn][18],n,m;
    int bin[50],Log[maxn],lenp,lent;
    inline void getsa(){
    	int *x = t1,*y = t2; m = 255;
    	for (res int i = 0; i <= m; i++) bac[i] = 0;
    	for (res int i = 1; i <= n; i++) bac[x[i] = s[i]]++;
    	for (res int i = 1; i <= m; i++) bac[i] += bac[i - 1];
    	for (res int i = n; i; i--) sa[bac[x[i]]--] = i;
    	for (res int k = 1; k <= n; k <<= 1){
    		int p = 0;
    		for (res int i = n - k + 1; i <= n; i++) y[++p] = i;
    		for (res int i = 1; i <= n; i++) if (sa[i] - k > 0) y[++p] = sa[i] - k;
    		for (res int i = 0; i <= m; i++) bac[i] = 0;
    		for (res int i = 1; i <= n; i++) bac[x[y[i]]]++;
    		for (res int i = 1; i <= m; i++) bac[i] += bac[i - 1];
    		for (res int i = n; i; i--) sa[bac[x[y[i]]]--] = y[i];
    		swap(x,y);
    		x[sa[1]] = p = 1;
    		for (res int i = 2; i <= n; i++)
    			x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k] ? p : ++p);
    		if (p >= n) break;
    		m = p;
    	}
    	for (res int i = 1; i <= n; i++) rank[sa[i]] = i;
    	for (res int i = 1,k = 0; i <= n; i++){
    		if (k) k--;
    		int j = sa[rank[i] - 1];
    		while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k++;
    		height[rank[i]] = k;
    	}
    	for (res int i = 1; i <= n; i++) mn[i][0] = height[i];
    	REP(j,17) REP(i,n){
    		if (i + bin[j] - 1 > n) break;
    		mn[i][j] = min(mn[i][j - 1],mn[i + bin[j - 1]][j - 1]);
    	}
    }
    inline int lcp(int x,int y){
    	int l = rank[x],r = rank[y];
    	if (l > r) swap(l,r); l++;
    	int t = Log[r - l + 1];
    	return min(mn[l][t],mn[r - bin[t] + 1][t]);
    }
    void solve(){
    	int ans = 0;
    	for (res int i = 1; i <= lenp - lent + 1; i++){
    		res int j = 1,tmp,cnt = 3;
    		while (cnt && j <= lent){
    			tmp = lcp(i + j - 1,lenp + 1 + j);
    			if (!tmp) j++,cnt--;
    			else j += tmp;
    		}
    		if (j <= lent){
    			j += lcp(i + j - 1,lenp + 1 + j);
    		}
    		if (j > lent){
    			ans++;
    		}
    	}
    	printf("%d
    ",ans);
    }
    int main(){
    	bin[0] = 1; REP(i,25) bin[i] = bin[i - 1] << 1;
    	Log[0] = -1; REP(i,200000) Log[i] = Log[i >> 1] + 1;
    	int T = read();
    	while (T--){
    		scanf("%s",s + 1); lenp = strlen(s + 1);
    		s[lenp + 1] = 1; s[lenp + 2] = '';
    		scanf("%s",s2 + 1); lent = strlen(s2 + 1);
    		strcat(s + 1,s2 + 1);
    		n = lenp + 1 + lent;
    		getsa();
    		solve();
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    无法加载文件或程序集“System.Net.Http,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a”
    Linux中安装Oracle jdk
    算符优先文法,中缀式求值,栈的典型应用
    数据结构之--双链表MyLinkedList
    数据结构之--单链表MyArrayList
    Java中的函数对象
    (11)连个工具类之间的比较4.Collections与Arrays
    javaList容器中容易忽略的知识点
    (27)回复泛型,注解、日志组件、枚举在实际项目中的使用
    无问西东,哪怕重头来过
  • 原文地址:https://www.cnblogs.com/Mychael/p/9049525.html
Copyright © 2011-2022 走看看