• luogu3763 [TJOI2017]DNA


    题目链接

    solution

    直接暴力后缀数组。

    将两个字符串接到一起,然后跑一遍后缀数组。

    因为可以有3个字符不同,那我们就枚举第一个字符串中和第二个字符串第一个字符相匹配的位置。从这个位置开始每次跳(LCP)长度。看跳4次之后能不能跳到最后就行了。

    (LCP)长度的时候用(ST)

    code

    /*
    * @Author: wxyww
    * @Date:   2020-04-20 20:00:41
    * @Last Modified time: 2020-04-20 21:00:47
    */
    #pragma GCC optimize ("O3")
    
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    const int N = 200010,logN = 20;
    ll read() {
    	ll x = 0,f = 1;char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1; c = getchar();
    	}
    	while(c >= '0' && c <= '9') {
    		x = x * 10 + c - '0'; c = getchar();
    	}
    	return x * f;
    }
    int n,m,sa[N],x[N],tn,y[N],c[N],st[N][logN + 2],rk[N],height[N];
    char s[N];
    void get_sa() {
    	for(int i = 1;i <= m;++i) c[i] = 0;
    	for(int i = 1;i <= n;++i) ++c[x[i] = s[i]];
    	for(int i = 1;i <= m;++i) c[i] += c[i - 1];
    	for(int i = n;i >= 1;--i) sa[c[x[i]]--] = i;
    	for(int k = 1;k <= n;k <<= 1) {
    		int num = 0;
    		for(int i = n - k + 1;i <= n;++i) y[++num] = i;
    		for(int i = 1;i <= n;++i) if(sa[i] > k) y[++num] = sa[i] - k;
    		for(int i = 1;i <= m;++i) c[i] = 0;
    		for(int i = 1;i <= n;++i) ++c[x[i]];
    		for(int i = 1;i <= m;++i) c[i] += c[i - 1];
    		for(int i = n;i >= 1;--i) sa[c[x[y[i]]]--] = y[i];
    		swap(x,y);
    		x[sa[1]] = num = 1;
    		for(int i = 2;i <= n;++i)
    			x[sa[i]] = (y[sa[i] + k] == y[sa[i - 1] + k] && y[sa[i]] == y[sa[i - 1]]) ? num : ++num;
    		m = num;
    		if(m == n) break;
    	}
    }
    void get_height() {
    	for(int i = 1;i <= n;++i) rk[sa[i]] = i;
    	int k = 0;
    	for(int i = 1;i <= n;++i) {
    		if(rk[i] == 1) continue;
    		if(k) --k;
    		int j = sa[rk[i] - 1];
    		while(i + k <= n && j + k <= n && s[i + k] == s[j + k]) ++k;
    		height[rk[i]] = k;
    	}
    }
    int lg[N];
    void get_st() {
    	for(int i = 1;i <= n;++i) st[i][0] = height[i];
    	for(int i = 2;i <= n;++i) lg[i] = lg[i >> 1] + 1;
    
    	for(int j = 1;(1 << j) <= n;++j) {
    		for(int i = 1;i <= n;++i) {
    			st[i][j] = min(st[i][j - 1],st[i + (1 << (j - 1))][j - 1]);
    		}
    	}
    }
    int get(int l,int r) {
    	if(l > r) swap(l,r);
    	++l;
    	return min(st[l][lg[r - l + 1]],st[r - (1 << lg[r - l + 1]) + 1][lg[r - l + 1]]);
    }
    
    void solve() {
    
    	scanf("%s",s + 1);
    	n = strlen(s + 1);
    	tn = n;
    	s[++n] = '#';
    	scanf("%s",s + n + 1);
    	n = strlen(s + 1);
    	// printf("%s",s + 1);puts("");
    	m = 'z';
    	get_sa();
    	get_height();
    	get_st();
    	// for(int i = 1;i <= n;++i) printf("%d ",sa[i]);puts("");
    	// for(int i = 1;i <= n;++i) printf("%d ",height[i]);puts("");
    	// puts("!!!");
    	// cout<<get(6,10)<<endl;
    	int ans = 0;
    	for(int i = 1;i + n - tn - 2 <= tn;++i) {
    		// printf("%d
    ",i);
    		int p = tn + 2;
    		for(int j = 1;j <= 4 && p <= n;++j) {
    			// if(i == 5) printf("!!%d %d %d
    ",i + p  - tn - 2,p,get(rk[i + (p - tn - 2)],rk[p]));
    			p += get(rk[i + (p - tn - 2)],rk[p]);
    			if(j != 4) ++p;
    		}
    		if(p > n) {
    			// cout<<i<<endl;
    			ans++;
    		}
    	}
    	printf("%d
    ",ans);
    
    }
    int main() {
    //	freopen("4892/7.in","r",stdin);
    	int T = read();
    	while(T--) {
    		solve();
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    「移动开发云端新模式探索实践」征文活动
    为数据赋能:腾讯TDSQL分布式金融级数据库前沿技术
    腾讯刘金明:腾讯云 EB 级对象存储架构深度剖析及实践
    腾讯冯宇彦:基于大数据与人工智能的智慧交通云
    腾讯毛华:智能交互,AI助力下的新生态
    腾讯聂晶:数据资产助力企业发展
    2018云+未来峰会圆桌面对面:以网络安全之能,造国之重器
    全景解析腾讯云安全:从八大领域输出全链路智慧安全能力
    为 “超级大脑”构建支撑能力,腾讯云聚焦AI技术落地
    web service介绍
  • 原文地址:https://www.cnblogs.com/wxyww/p/luogu3763.html
Copyright © 2020-2023  润新知