zoukankan      html  css  js  c++  java
  • 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;
    }
    字符串
  • 相关阅读:
    用Bootstrap框架弹出iframe页面 在弹出的模态框中载人iframe页面,bootstrapiframe
    Jquery Ajax表单提交插件jquery form用法
    ASP.NET MVC 在控制器中接收视图表单POST过来的数据方法
    RabbitMQ用户管理+VirtualHost管理
    Linux 查看Oracle 信息
    页面元素的坐标位置
    Selenium之Action Chains类
    测试管理:用量化的思想管理工作
    Python selenium ---父子,兄弟,相邻节点定位方式详解
    webdriver 清空input元素的值
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13547006.html
Copyright © 2011-2022 走看看