BZOJ3473 字符串

Description

给定$n$个字符串,询问每个字符串有多少子串(不包括空串)是所有$n$个字符串中至少$k$个字符串的子串?

Solution

建广义后缀自动机,对于每一个字符串给它的所有子串节点计数,在parent树上从根向下合并,对于每个字符串,答案为其所有前缀的权值和,时间复杂度$O(n sqrt n)$(由均值不等式可证)

数据:链接:https://pan.baidu.com/s/17yytL_cLsivciz4Mpos3GA  提取码:se5o

#pragma GCC optimize(2)
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
int n,k,tot=1,las=1,buc[200005],topo[200005];
long long dp[200005];
char str[200005];
string s[200005];
struct SAM
{
    int ch[26],len,fa,cnt,col;
}sam[200005];
inline int read()
{
    int w=0,f=1;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+ch-'0';
        ch=getchar();
    }
    return w*f;
}
void insert(int c)
{
    int p=las,np=las=++tot;
    sam[np].len=sam[p].len+1;
    for(;p&&!sam[p].ch[c];p=sam[p].fa)
    {
        sam[p].ch[c]=np;
    }
    if(!p)
    {
        sam[np].fa=1;
    }
    else
    {
        int q=sam[p].ch[c];
        if(sam[q].len==sam[p].len+1)
        {
            sam[np].fa=q;
        }
        else
        {
            int nq=++tot;
            sam[nq]=sam[q];
            sam[nq].len=sam[p].len+1;
            sam[q].fa=sam[np].fa=nq;
            for(;p&&sam[p].ch[c]==q;p=sam[p].fa)
            {
                sam[p].ch[c]=nq;
            }
        }
    }
}
int main()
{
    n=read();
    k=read();
    for(int i=1;i<=n;i++)
    {
        scanf("%s",str);
        s[i]=string(str);
        las=1;
        for(int j=0;str[j];j++)
        {
            insert(str[j]-'a');
        }
    }
    for(int i=1;i<=n;i++)
    {
        int p=1;
        for(int j=0;s[i][j];j++)
        {
            p=sam[p].ch[s[i][j]-'a'];
            int temp=p;
            while(temp)
            {
                if(sam[temp].col!=i)
                {
                    sam[temp].col=i;
                    ++sam[temp].cnt;
                }
                else
                {
                    break;
                }
                temp=sam[temp].fa;
            }
        }
    }
    for(int i=1;i<=tot;i++)
    {
        ++buc[sam[i].len];
    }
    for(int i=1;i<=tot;i++)
    {
        buc[i]+=buc[i-1];
    }
    for(int i=1;i<=tot;i++)
    {
        topo[buc[sam[i].len]--]=i;
    }
    sam[1].cnt=0;
    for(int i=1;i<=tot;i++)
    {
        dp[topo[i]]+=dp[sam[topo[i]].fa];
        if(sam[topo[i]].cnt>=k)
        {
            dp[topo[i]]+=sam[topo[i]].len-sam[sam[topo[i]].fa].len;
        }
    }
    for(int i=1;i<=n;i++)
    {
        long long ans=0,p=1;
        for(int j=0;s[i][j];j++)
        {
            p=sam[p].ch[s[i][j]-'a'];
            ans+=dp[p];
        }
        printf("%lld ",ans);
    }
    return 0;
}
字符串
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13547006.html