zoukankan      html  css  js  c++  java
  • [NOI Online 2021 提高组] 积木小赛

    [NOI Online 2021 提高组] 积木小赛

    题目大意:给定串(A),(B),求(B)中有多少本质不同的连续子段是(A)的子序列

    (nleq 3000)

    暴力枚举(B)中的子段,同步维护与(A)的匹配指针(p)

    每次插入一个字符(c),找到(A)(p+1)之后第一个字符(c),令匹配指针跳过去

    可以预处理出这样的下一个字符(nxt_{i,c}),完成(O(1))匹配

    除此以外,我们还需要对于本质不同去重

    如果用( ext{trie})树去重,需要开一个(frac{n^2}{2}cdot 26)的数组,面临着内存不够的问题

    你可以信仰不开这么大

    也可以去学习一下( ext{DAT(Double Array Trie)})算法

    也可以用( ext{hash+set/map/hash table/sort unique})

    也可以用链表暴力存储trie树的情况,每次暴力for过去找儿子

    这样内存均为(O(n^2))

    以下是链表trie树的版本

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double db;
    typedef pair <int,int> Pii;
    #define reg register
    #define mp make_pair
    #define pb push_back
    #define Mod1(x) ((x>=P)&&(x-=P))
    #define Mod2(x) ((x<0)&&(x+=P))
    #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
    template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
    template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
    
    char IO;
    template <class T=int> T rd(){
    	T s=0; int f=0;
    	while(!isdigit(IO=getchar())) f|=IO=='-';
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const int N=3010,M=N*N/2,INF=1e9+10;
    bool Mbe;
    
    int n;
    int nxt[N][26];
    char A[N],B[N];
    struct Edge{ int c,to,nxt; } e[M];
    int head[M],cnt;
    
    bool Med;
    int main(){
    	//fprintf(stderr,"%.2lf
    ",(&Med-&Mbe)/1024.0/1024.0);
    	freopen("block.in","r",stdin),freopen("block.out","w",stdout);
    	n=rd(),scanf("%s%s",A+1,B+1);
    	drep(i,n,1) {
    		rep(j,0,25) nxt[i][j]=nxt[i+1][j];
    		nxt[i][A[i]-'a']=i;
    	}
    	rep(i,1,n) {
    		int u=0,p=0;
    		rep(j,i,n) {
    			int c=B[j]-'a';
    			if(!(p=nxt[p+1][c])) break;
    			int v=-1;
    			for(int k=head[u];k;k=e[k].nxt) if(e[k].c==c) { v=e[k].to; break; }
    			if(~v) u=v;
    			else {
    				v=++cnt;
    				e[v]=(Edge){c,v,head[u]};
    				head[u]=v,u=v;
    			}
    		}
    	}
    	printf("%d
    ",cnt);
    }
    
  • 相关阅读:
    elasticsearch7.1 安装启动报错
    jvm调优
    基于redis实现IP访问频次控制
    docker 搭建redis集群
    Tomcat安全配置与性能优化
    mybaties 的 applicationContext.xml
    SSH阶段常见错误及说明
    hibernate 7种映射关系
    (四)SpringBoot如何定义消息转换器
    java之package与import
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14585451.html
Copyright © 2011-2022 走看看