zoukankan      html  css  js  c++  java
  • 【BZOJ3413】—匹配(后缀自动机+线段树合并)

    传送门

    相当于对每个询问串询问和一堆串的lcplcp

    考虑对询问串的每一位ii分别考虑会和多少个串匹配到这一位
    假设最后末尾在pp匹配上
    那显然就是当前这一位对应的节点的endposendpos[i,p+ilen][i,p+i-len]范围内
    如果一直没匹配上就是[i,n][i,n]

    然后线段树合并维护endposendpos就完了

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define pic pair<int,char>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    #define poly vector<int>
    template<class T>inline void chemx(T &a,T &b){a<b?a=b:0;}
    template<class T>inline void chemn(T &a,T &b){a>b?a=b:0;}
    cs int N=100005;
    int n,m;
    namespace Seg{
    	cs int M=N*50;
    	int lc[M],rc[M],siz[M],tot;
    	#define mid ((l+r)>>1)
    	inline void insert(int &u,int l,int r,int p){
    		u=++tot;siz[u]++;
    		if(l==r)return;
    		if(p<=mid)insert(lc[u],l,mid,p);
    		else insert(rc[u],mid+1,r,p);
    	}
    	inline void merge(int &u,int r1,int r2){
    		if(!r1||!r2){u=r1+r2;return;}
    		u=++tot,siz[u]=siz[r1]+siz[r2];
    		merge(lc[u],lc[r1],lc[r2]);
    		merge(rc[u],rc[r1],rc[r2]);
    	}
    	inline int query(int u,int l,int r,int st,int des){
    		if(!u)return 0;
    		if(st<=l&&r<=des)return siz[u];
    		int res=0;
    		if(st<=mid)res+=query(lc[u],l,mid,st,des);
    		if(mid<des)res+=query(rc[u],mid+1,r,st,des);
    		return res;
    	}
    }
    namespace Sam{
    	cs int M=N*2;
    	int len[M],fa[M],nxt[M][10],pos[M],ed[N],rt[M];
    	int tot,last;
    	inline void init(){
    		tot=last=1;
    	}
    	inline void insert(int c,int id){
    		int cur=++tot,p=last;last=cur;
    		ed[id]=cur,pos[cur]=id;
    		len[cur]=len[p]+1;
    		for(;p&&!nxt[p][c];p=fa[p])nxt[p][c]=cur;
    		if(!p)fa[cur]=1;
    		else{
    			int q=nxt[p][c];
    			if(len[p]+1==len[q])fa[cur]=q;
    			else{
    				int clo=++tot;
    				fa[clo]=fa[q],len[clo]=len[p]+1;
    				memcpy(nxt[clo],nxt[q],sizeof(nxt[q]));
    				for(;p&&nxt[p][c]==q;p=fa[p])nxt[p][c]=clo;
    				fa[cur]=fa[q]=clo;
    			}
    		}
    	}
    	int buc[M],rk[M];
    	inline void build(){
    		for(int i=1;i<=tot;i++)buc[len[i]]++;
    		for(int i=1;i<=tot;i++)buc[i]+=buc[i-1];
    		for(int i=1;i<=tot;i++)rk[buc[len[i]]--]=i;
    		for(int i=tot;i>=1;i--){
    			int u=rk[i];
    			if(pos[u])Seg::insert(rt[u],1,n,pos[u]);
    			Seg::merge(rt[fa[u]],rt[fa[u]],rt[u]);
    			if(!pos[u])pos[u]=1e9;
    		}
    		for(int i=tot;i>=1;i--){
    			int u=rk[i];
    			chemn(pos[fa[u]],pos[u]);
    		}
    	}
    	inline ll query(char *s){
    		ll res=0;int p=1,fg=0,l=strlen(s+1),lim;
    		for(int i=1;i<=l;i++){
    			int c=s[i]-'0';
    			if(!nxt[p][c]){fg=1;break;}
    			p=nxt[p][c];
    		}
    		if(fg==1)res=n,lim=n;
    		else lim=pos[p],res=(lim-l);
    		p=1;
    		for(int i=1;i<=l;i++){
    			int c=s[i]-'0';
    			if(!nxt[p][c])break;
    			p=nxt[p][c];
    			res+=Seg::query(rt[p],1,n,i,fg?n:(lim+i-l));
    		}
    		return res;
    	}
    }
    char s[N];
    int main(){
    	Sam::init();
    	n=read();
    	scanf("%s",s+1);
    	for(int i=1;i<=n;i++)Sam::insert(s[i]-'0',i);
    	Sam::build();
    	m=read();
    	for(int i=1;i<=m;i++){
    		scanf("%s",s+1);
    		cout<<Sam::query(s)<<'
    ';
    	}
    }
    
  • 相关阅读:
    正则表达式学习笔记(3)字符类
    一个Service/Functional/Persistence的简单框架
    在Visual Studio 2008环境下安装Boost
    你需要掌握的三种编程语言
    abstract、virtual、override 和 new
    WINCE下编译STLPort
    VS2008环境下编译使用SGI STL(using stlport 5.2.1)
    QT For WinCE, Visual Studio 2008环境的搭建
    VC6.0、VS2005、VS2008安装STLport5.2.1
    Ubuntu 11.10 安装nginx+php5+mysql 的web服务器
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328441.html
Copyright © 2011-2022 走看看