• [BZOJ3413]匹配


    bzoj

    description

    sol

    首先你要求出(s_i)第一次匹配的位置。(或者是没有匹配位置)
    然后问题就大致转化为了:求(s_i)和原串中第一次匹配位置之前的所有后缀的(lcp)之和。(有一些小细节就自己(yy)一下吧)
    这个问题显得不是那么好做,考虑把这个问题转化一下,改为求(s_i)的每个前缀在匹配位置之前的出现次数。
    然后看上去就很简单了?对(SAM)线段树合并(endpos)集合,然后一边跑匹配一边线段树区间查询。复杂度(O(sum len imeslog n))

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 2e5+5;
    struct seg{int ls,rs,sz;}t[N*40];
    int n,q,tot=1,last=1,tr[N][10],fa[N],len[N],rt[N],Node,tong[N],a[N];
    char s[N];
    void extend(int c){
    	int v=last,u=++tot;last=u;
    	len[u]=len[v]+1;
    	while (v&&!tr[v][c]) tr[v][c]=u,v=fa[v];
    	if (!v) fa[u]=1;
    	else{
    		int x=tr[v][c];
    		if (len[x]==len[v]+1) fa[u]=x;
    		else{
    			int y=++tot;
    			memcpy(tr[y],tr[x],sizeof(tr[y]));
    			fa[y]=fa[x];fa[x]=fa[u]=y;len[y]=len[v]+1;
    			while (v&&tr[v][c]==x) tr[v][c]=y,v=fa[v];
    		}
    	}
    }
    void modify(int &x,int l,int r,int p){
    	if (!x) x=++Node;++t[x].sz;
    	if (l==r) return;int mid=l+r>>1;
    	if (p<=mid) modify(t[x].ls,l,mid,p);
    	else modify(t[x].rs,mid+1,r,p);
    }
    int merge(int x,int y){
    	if (!x||!y) return x|y;
    	int z=++Node;t[z].sz=t[x].sz+t[y].sz;
    	t[z].ls=merge(t[x].ls,t[y].ls);
    	t[z].rs=merge(t[x].rs,t[y].rs);
    	return z;
    }
    int find(int x,int l,int r){
    	if (l==r) return l;int mid=l+r>>1;
    	if (t[t[x].ls].sz) return find(t[x].ls,l,mid);
    	else return find(t[x].rs,mid+1,r);
    }
    int query(int x,int l,int r,int ql,int qr){
    	if (l>=ql&&r<=qr) return t[x].sz;
    	int mid=l+r>>1,res=0;
    	if (ql<=mid) res+=query(t[x].ls,l,mid,ql,qr);
    	if (qr>mid) res+=query(t[x].rs,mid+1,r,ql,qr);
    	return res;
    }
    int main(){
    	n=gi();scanf("%s",s+1);
    	for (int i=1;i<=n;++i) extend(s[i]-'0'),modify(rt[last],1,n,i);
    	for (int i=1;i<=tot;++i) ++tong[len[i]];
    	for (int i=1;i<=n;++i) tong[i]+=tong[i-1];
    	for (int i=1;i<=tot;++i) a[tong[len[i]]--]=i;
    	for (int i=tot;i>1;--i) rt[fa[a[i]]]=merge(rt[fa[a[i]]],rt[a[i]]);
    	q=gi();while (q--){
    		scanf("%s",s+1);int l=strlen(s+1),now=1,lst;
    		long long ans=0;
    		for (int i=1;i<=l;++i) now=tr[now][s[i]-'0'];
    		if (now) lst=find(rt[now],1,n),ans=lst-l;
    		else lst=-1,ans=n;
    		now=1;
    		for (int i=1;i<=l;++i){
    			now=tr[now][s[i]-'0'];
    			if (now) ans+=query(rt[now],1,n,1,lst==-1?n:lst-l+i);
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    每日总结
    每日总结
    Panda Global要点聚焦,中国应加快布局迎接区块链发展升温
    Panda Global热点关注,区块链在物流行业的应用
    Panda 交易所为你解读,区块链提速有望推动数字经济更广阔发展
    Panda 交易所视点观察,金融场景区块链应用进程已经不可逆转
    Panda 交易所焦点观察,区块链技术在各国政府管理中的运用
    Panda 交易所前沿解读,完善顶层设计 构筑区块链创新创业人才高地
    Panda 交易所热点关注,支持区块链技术发展 赋能数字经济
    区块链技术会给我们的生活带来哪些影响?Panda Global 带你一文看懂!
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9200987.html
Copyright © 2020-2023  润新知