• LG4696 Matching


    Matching

    对于整数序列 ((a_1,a_2,cdots,a_n))(1sim n) 的排列 ((p_1,p_2,cdots,p_n)),称 ((a_1,a_2,cdots,a_n)) 符合 ((p_1,p_2,cdots,p_n)),当且仅当: - ({a}) 中任意两个数字互不相同; - 将 ((a_1,a_2,cdots,a_n)) 从小到大排序后,将会得到 ((a_{p_1},a_{p_2},cdots,a_{p_n}))。 现在给出 (1sim n) 的排列 ({p}) 和序列 (h_1,h_2,cdots,h_m)​​,请你求出哪些 ({h}) 的子串符合排列 ({p})

    对于 (100\%) 的数据,有 (2le nle mle 1 000 000;1le h_ile 10^9;1le p_ile n),保证 ({h}) 中的元素互不相同,且 ({p}) 是一个排列。

    题解

    https://www.luogu.com.cn/blog/118846/solution-p4696

    重新实现KMP过程,比较简单的思路就是判断排名是否一致,可以离散化+树状数组解决。时间复杂度 (O(n log n))

    还有更快的方法,只判断值域的前驱后继的大小关系是否一致。时间复杂度 (O(n))

    CO int N=1e6+10;
    int a[N],b[N];
    int pre[N],nex[N],L[N],R[N];
    int fa[N],s[N];
    
    IN bool check(int p[],int i,int u){
    	return p[u+L[i]]<=p[u] and p[u+R[i]]>=p[u];
    }
    int main(){
    	int n=read<int>(),m=read<int>();
    	for(int i=1;i<=n;++i){
    		read(b[i]); // rank -> index
    		a[b[i]]=i; // index -> rank
    		pre[i]=i-1,nex[i]=i+1; // two-way linked-list
    	}
    	for(int i=n;i>=1;--i){
    		int j=a[i];
    		if(pre[j]>=1) L[i]=b[pre[j]]-i;
    		if(nex[j]<=n) R[i]=b[nex[j]]-i;
    		pre[nex[j]]=pre[j],nex[pre[j]]=nex[j];
    	}
    	for(int i=2;i<=n;++i){
    		int j=fa[i-1];
    		while(j and !check(a,j+1,i)) j=fa[j];
    		fa[i]=j+check(a,j+1,i);
    	}
    	for(int i=1;i<=m;++i) read(s[i]);
    	vector<int> ans;
    	for(int i=1,j=0;i<=m;++i){
    		while(j and !check(s,j+1,i)) j=fa[j];
    		j+=check(s,j+1,i);
    		if(j==n){
    			ans.push_back(i-n+1);
    			j=fa[j];
    		}
    	}
    	printf("%zd
    ",ans.size());
    	for(int x:ans) printf("%d ",x);
    	puts("");
    	return 0;
    }
    
  • 相关阅读:
    Nginx 缓存解决方案
    Chrome去水印、自由复制的解决方法
    简单介绍正向代理和反向代理
    Lambda表达式
    项目集成hystrix-dashboard
    hystrix 添加turbine
    GsonUtil 工具类
    idea 去除import * 变成具体引入文件
    eureka 创建服务消费者
    eureka 创建注册服务提供方
  • 原文地址:https://www.cnblogs.com/autoint/p/12334745.html
Copyright © 2020-2023  润新知