zoukankan      html  css  js  c++  java
  • Codeforces 316G3 Good Substrings 字符串 SAM

    原文链接http://www.cnblogs.com/zhouzhendong/p/9010851.html

    题目传送门 - Codeforces 316G3

    题意

      给定一个母串$s$,问母串$s$有多少本质不同的子串$t$是“好”的。

      一个字符串$t$是好的,仅当$t$满足了所有的$n$个条件。

      第$i$个条件用一个三元组$(p_i,L_i,R_i)$来描述。

      其中$p_i$为一个字符串,$L_i,R_i$为整数,且$L_ileq R_i$。

      仅当字符串$t$在$p_i$中出现次数在$L_i$到$R_i$之间时,它是"好"的。

      $|s|,|p_i|leq 5 imes 10^4,nleq 10$

    题解

      考虑把输入的$n+1$个字符串用特殊字符隔开,并练成一个串。

      为了方便,我们将母串$s$放在第一个,$n$条规则中的字符串依次连续。

      我们定义数组$tot[i][j]$表示后缀自动机状态$i$的$Right$集合中有多少个位置处于第$j$个串。其中母串为第$0$个串,$p_i$为第$i$个串。

      这个可以通过基数排序+$dp$来搞定。

      然后我们分状态统计。

      对于状态$i$,如果$tot[i][0]=0$,那么说明这个状态所表示的一些串不存在于母串中,所以可以跳过。

      否则$tot[i][0]>0$,这个状态所表示的一些串存在于母串中。由于母串中没有特殊的字符,所以这个状态所表示的一些串也没有特殊字符,所以,对于已经得到的计数$tot[i][1cdot n]$中也没有统计到包含特殊字符的子串。

      如果当前状态被计入,那么需要满足所有的$n$个条件,即$forall 1leq jleq n, L_jleq tot[i][j]leq R_j$。当前状态包含的本质不同的串的个数显然为$Max(i)-Min(i)+1=Max(i)-Max(fa(i))$。加到答案里就可以了。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=550005;
    int n,m,L[15],R[15];
    int size=1,root=1,last=1;
    int tax[N<<1],id[N<<1];
    LL tot[N<<1][12];
    char s[N];
    struct SAM{
    	int Next[27],fa,Max;
    }t[N<<1];
    void extend(int c,int id){
    	int p=last,np=++size,q,nq;
    	tot[np][id]++;
    	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[q].Max==t[p].Max+1)
    		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;
    	}
    	last=np;
    }
    int main(){
    	t[0].Max=-1;
    	for (int i=0;i<27;i++)
    		t[0].Next[i]=1;
    	scanf("%s",s);
    	m=strlen(s);
    	for (int i=0;i<m;i++)
    		extend(s[i]-'a',0);
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++){
    		extend(26,n+1);
    		scanf("%s%d%d",s,&L[i],&R[i]);
    		m=strlen(s);
    		for (int j=0;j<m;j++)
    			extend(s[j]-'a',i);
    	}
    	for (int i=1;i<=size;i++)
    		tax[t[i].Max]++;
    	for (int i=1;i<=size;i++)
    		tax[i]+=tax[i-1];
    	for (int i=1;i<=size;i++)
    		id[tax[t[i].Max]--]=i;
    	LL ans=0;
    	for (int i=size;i>=2;i--){
    		int x=id[i];
    		for (int j=0;j<=n;j++)
    			tot[t[x].fa][j]+=tot[x][j];
    		if (tot[x][0]==0)
    			continue;
    		bool flag=1;
    		for (int j=1;flag&&j<=n;j++)
    			flag&=L[j]<=tot[x][j]&&tot[x][j]<=R[j];
    		if (flag)
    			ans+=t[x].Max-t[t[x].fa].Max;
    	}
    	printf("%I64d",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    java.lang.IllegalStateException: Cannot get a STRING value from a NUMERIC cell
    spring boot 启动报:Composite-id class must implement Serializable: xxx错误
    IntelliJ IDEA 中使用region代码折叠
    JSON parse error: Cannot deserialize value of type `java.time.LocalDateTime` from String
    MySQL生成UUID
    PowerDesigner设计表时显示注释列Comment,Columns中没有Comment的解决办法
    使用PowerDesigner创建物理模型并生成SQL语句在MySQL中生成表
    IMP-00003: 遇到 ORACLE 错误 959 ORA-00959: 表空间 '' 不存在
    SP2-0734: 未知的命令开头 “IMP ”
    使用imp命令和exp命令对oracle数据库进行导入导出操作
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/CF316G3.html
Copyright © 2011-2022 走看看