zoukankan      html  css  js  c++  java
  • Codeforces 452E Three strings 字符串 SAM

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF542E.html

    题目传送门 - CF452E

    题意

      给定三个字符串 $s1,s2,s3$ ,对于所有 $Lin{1,2,cdots,min(|s1|,|s2|,|s3|)}$ ,输出 $f(L)$ 。

      其中 $f(L)$ 表示满足 $s_k[i_k,cdots,i_k+L-1]$ 全部相同的 $i_1,i_2,i_3$ 的个数。

      答案对 $10^9+7$ 取模。

      $|s1|+|s2|+|s3|leq 3 imes 10^5$

    题解

      第二次写广义后缀自动机,居然又只写了 20 分钟??然而没有看到取模,以及一个取模上面的傻逼错误续了我 15 分钟。

      把三个串全部扔进广义后缀自动机里面。

      对于每一个状态,分别算出属于这三个串的 right 集合大小。

      然后对于每一个节点,方案总数就是 $prod_{k=0}^{2}right_{i,k}$ ,影响的长度范围是 $( m{Max(father),Max(i)}]$ ,相当于区间加,直接差分一下就可以了。

      最后回答的时候前缀和一下就好了。注意取模。

    代码

    #include <bits/stdc++.h>
    #define right __fjw82
    using namespace std;
    const int N=300005,S=N*2,mod=1e9+7;
    char s[N];
    int n=1e9,in[S],q[S],ans[N],right[S][3],head,tail;
    int root,size;
    struct SAM{
    	int Next[26],fa,Max;
    }t[N<<1];
    void init(){
    	memset(t,0,sizeof t);
    	root=size=1;
    	t[0].Max=-1;
    	for (int i=0;i<26;i++)
    		t[0].Next[i]=1;
    }
    int extend(int p,int c){
    	if (t[p].Next[c]&&t[p].Max+1==t[t[p].Next[c]].Max)
    		return t[p].Next[c];
    	int np=++size,q,nq;
    	t[np].Max=t[p].Max+1;
    	for (;!t[p].Next[c];p=t[p].fa)
    		t[p].Next[c]=np;
    	q=t[p].Next[c];
    	if (t[p].Max+1==t[q].Max)
    		t[np].fa=q;
    	else {
    		nq=++size;
    		t[nq]=t[q],t[nq].Max=t[p].Max+1;
    		t[q].fa=t[np].fa=nq;
    		for (;t[p].Next[c]==q;p=t[p].fa)
    			t[p].Next[c]=nq;
    	}
    	return np;
    }
    int main(){
    	init();
    	for (int i=0,now;i<3;i++){
    		scanf("%s",s+1);
    		n=min(n,now=strlen(s+1));
    		for (int j=1,p=root;j<=now;j++)
    			right[p=extend(p,s[j]-'a')][i]++;
    	}
    	for (int i=2;i<=size;i++)
    		in[t[i].fa]++;
    	head=tail=0;
    	for (int i=2;i<=size;i++)
    		if (in[i]==0)
    			q[++tail]=i;
    	while (head<tail){
    		int x=q[++head];
    		for (int i=0;i<3;i++)
    			right[t[x].fa][i]+=right[x][i];
    		in[t[x].fa]--;
    		if (t[x].fa>1&&!in[t[x].fa])
    			q[++tail]=t[x].fa;
    	}
    	memset(ans,0,sizeof ans);
    	for (int i=2;i<=size;i++){
    		int add=1LL*right[i][0]*right[i][1]*right[i][2]%mod;
    		(ans[t[t[i].fa].Max+1]+=add)%=mod;
    		(ans[t[i].Max+1]+=mod-add)%=mod;
    	}
    	for (int i=1;i<=n;i++){
    		ans[i]=(ans[i]+ans[i-1])%mod;
    		printf("%d ",ans[i]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    腾讯收购的《部落冲突》开发商有多牛?(这几个哥们真牛,什么技术都会,还能做出工业级的产品)
    人类最强大的一句话,可能就是三个字:我不要!
    Qt发展历史及其特点简介(没有哪一种方案能够独霸Windows)
    SpringMVC入门
    23种设计模式
    .NET序列化的一点技巧(附Demo)
    系统分层演变
    MVC程序中实体框架的连接恢复和命令拦截
    Mocha JavaScript TDD
    小型网站快速建设
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/CF452E.html
Copyright © 2011-2022 走看看