• bzoj 3277: 串


    题目

    这里是一种建广义(SAM)的新姿势,就是每次都把(last)置成(1)

    看起来也没什么科学的地方,但是这就是建广义(SAM)的方法

    之后我们对于那些新插入的位置我们给它涂上颜色

    显然对于一个出现次数超过(k)次的子串,其子树内部必然有超过(k)种颜色

    我们来一遍(hh)的项链就可以统计出来所有节点子树内部的颜色个数了

    之后对于每一个串的每一个前缀我们统计其出现次数超过(k)的后缀

    由于知道这个后缀前缀的结尾,我们直接树上倍增就好了,一直往上跳颜色次数小于(k)的节点,最后再跳一次就是了

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #define maxn 200005
    #define re register 
    #define LL long long
    #define lowbit(x) ((x)&(-x))
    int lst=1,cnt=1,n,K,num,__;
    struct E{int v,nxt;}e[maxn];
    struct Ask{int x,y,rk;}a[maxn];
    std::vector<int> pos[maxn>>1];
    char S[maxn>>1]; int c[maxn],pre[maxn>>1];
    int fa[maxn],len[maxn],son[maxn][26],t[maxn],sz[maxn],to[maxn];
    int deep[maxn],lg2[maxn],_to[maxn],val[maxn],head[maxn],f[maxn][20];
    inline int cmp(Ask A,Ask B) {return A.y<B.y;}
    inline void add_(int x,int y){e[++num].v=y;e[num].nxt=head[x];head[x]=num;} 
    inline void add(int x,int val){for(re int i=x;i<=cnt;i+=lowbit(i)) c[i]+=val;}
    inline int ask(int x){int now=0;for(re int i=x;i;i-=lowbit(i)) now+=c[i];return now;}
    void dfs(int x) {
    	to[x]=++__,_to[__]=x;sz[x]=1;
    	for(re int i=head[x];i;i=e[i].nxt) deep[e[i].v]=deep[x]+1,dfs(e[i].v),sz[x]+=sz[e[i].v];
    }
    inline void ins(int c,int o)
    {
    	int p=++cnt,f=lst; lst=p;
    	len[p]=len[f]+1,t[p]=o;pos[o].push_back(p);
    	while(f&&!son[f][c]) son[f][c]=p,f=fa[f];
    	if(!f) {fa[p]=1;return;}
    	int x=son[f][c];
    	if(len[f]+1==len[x]) {fa[p]=x;return;}
    	int y=++cnt;
    	len[y]=len[f]+1,fa[y]=fa[x],fa[x]=fa[p]=y;
    	for(re int i=0;i<26;i++) son[y][i]=son[x][i];
    	while(f&&son[f][c]==x) son[f][c]=y,f=fa[f];
    } 
    int main()
    {
    	scanf("%d%d",&n,&K);
    	for(re int i=1;i<=n;i++)
    	{
    		scanf("%s",S+1);
    		int L=strlen(S+1);lst=1;
    		for(re int j=1;j<=L;j++) ins(S[j]-'a',i);
    	}
    	for(re int i=2;i<=cnt;i++) add_(fa[i],i); deep[1]=1,dfs(1);
    	for(re int i=1;i<=cnt;i++) a[i].rk=i,a[i].x=to[i],a[i].y=to[i]+sz[i]-1;
    	std::sort(a+1,a+cnt+1,cmp); int now=1;
    	for(re int i=1;i<=cnt;i++)
    	{
    		if(t[_to[i]])
    		{
    			if(pre[t[_to[i]]]) add(pre[t[_to[i]]],-1);
    			add(i,1),pre[t[_to[i]]]=i;
    		}
    		while(a[now].y==i) val[a[now].rk]=ask(a[now].y)-ask(a[now].x-1),now++;
    	}
    	for(re int i=1;i<=cnt;i++) f[i][0]=fa[i];
    	for(re int i=2;i<=cnt;i++) lg2[i]=lg2[i>>1]+1;
    	for(re int j=1;j<=lg2[cnt];j++)
    		for(re int i=1;i<=cnt;i++) f[i][j]=f[f[i][j-1]][j-1];
    	for(re int i=1;i<=n;i++)
    	{
    		LL ans=0;
    		for(re int j=0;j<pos[i].size();j++)
    		{
    			int T=pos[i][j];
    			for(re int k=lg2[deep[T]];k>=0;k--) 
    				if(val[f[T][k]]<K&&f[T][k]) T=f[T][k];
    			if(val[T]<K) T=fa[T];
    			ans+=len[T];
    		}
    		printf("%lld ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Python 学习日记 第七天
    Python 学习日记 第六天
    Python 学习日记 第五天
    Python 学习日记 第四天
    Redis 中的数据类型及基本操作
    Asp.net mvc 中View 的呈现(二)
    Asp.net mvc 中View的呈现(一)
    Asp.net mvc 中Action 方法的执行(三)
    Asp.net mvc 中Action 方法的执行(二)
    Asp.net mvc 中Action 方法的执行(一)
  • 原文地址:https://www.cnblogs.com/asuldb/p/10267757.html
Copyright © 2020-2023  润新知