zoukankan      html  css  js  c++  java
  • bzoj 3277 串 && bzoj 3473 字符串 && bzoj 2780 [Spoj]8093 Sevenk Love Oimaster——广义后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3277

       https://www.lydsy.com/JudgeOnline/problem.php?id=3473

    学习的博客:https://www.cnblogs.com/HocRiser/p/9580478.html

    广义后缀自动机有两种写法,这里写的是 trie 树的那种。

    大意就是每个串从自动机的根开始走,

    1.如果存在 q = go[p][w] ,且 l [q] == l [p]+1 ,  那么直接把 q 看作这次插入了的点,下次令 p = q ,续着往后插入;

    2.如果存在 q = go[p][w] ,且 l [q] != l [p]+1 , 那么分出一个 nq 来,把 nq 看作这次插入了的点,下次令 p = nq ,续着往后插入;

    3.如果不存在 q = go[p][w] ,就新建一个 np ;然后就是一个串的后缀自动机插入了;下次令 p = np 。

    要计算后缀自动机上的每个点代表的那些子串在所有串里出现了多少次,记为 ct[ ] ;

      在做一个串的插入的时候,考虑让一些位置的 ct[ ] ++ ;每插入一个字符,就跳 fa ,给所有 fa 的 ct[ ] ++ ;但如果已经被当前字符串的之前字符弄得 ct[ ] 加一过了,就不用再加了;

      不要边建自动机边做 ct[ ] ++ ;因为那时的 parent 树还不是所有串的。

    然后拓扑排序一下,从根到叶子做 dp ,自己节点可以贡献的合法子串个数 ans[ ] 就是 ans[ fa ] 再加上 “ 自己出现了 >= k 次?l [cr] - l [fa] : 0 ” 。

    两道题用同样的代码即可。

    #include<cstdio>
    #include<cstring>
    #include<string>//
    #include<algorithm>
    #define ll long long
    using namespace std;
    int Mx(int a,int b){return a>b?a:b;}
    const int N=1e5+5,M=N<<1,K=27;//<<1
    int n,k,go[M][K],l[M],fa[M],tot=1;
    int tx[M],q[M],ans[M],ct[M],vis[M];
    int cz(int p,int w)
    {
      int q=go[p][w],nq=++tot;l[nq]=l[p]+1;
      fa[nq]=fa[q];fa[q]=nq;
      memcpy(go[nq],go[q],sizeof go[q]);
      for(;p&&go[p][w]==q;p=fa[p])go[p][w]=nq;
      return nq;
    }
    int ins(int p,int w)
    {
      if(go[p][w])
        {
          int q=go[p][w];
          if(l[q]==l[p]+1)return go[p][w];
          else return cz(p,w);//////
        }
      else
        {
          int np=++tot;l[np]=l[p]+1;
          for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
          if(!p)fa[np]=1;
          else
        {
          int q=go[p][w];
          if(l[q]==l[p]+1)fa[np]=q;
          else fa[np]=cz(p,w);
        }
          return np;
        }
    }
    void Rsort(int mxn)
    {
      for(int i=1;i<=tot;i++)tx[l[i]]++;
      for(int i=1;i<=mxn;i++)tx[i]+=tx[i-1];
      //  for(int i=tot;i;i--)q[tx[l[i]]--]=i;
      for(int i=1;i<=tot;i++)q[tx[l[i]]--]=i;
    }
    string ch[N]; int len[N];
    int main()
    {
      scanf("%d%d",&n,&k); char tp[N]; int mxn=0;
      for(int i=1,d;i<=n;i++)
        {
          scanf("%s",tp);len[i]=strlen(tp);mxn=Mx(mxn,len[i]);
          ch[i]=tp;
        }
      for(int i=1;i<=n;i++)
        for(int lm=len[i],pr=1,j=0;j<lm;j++)
          pr=ins(pr,ch[i][j]-'a'+1);
      for(int i=1;i<=n;i++)
        for(int lm=len[i],cr=1,j=0;j<lm;j++)
          {
        cr=go[cr][ch[i][j]-'a'+1];
        for(int p=cr;p&&vis[p]!=i;p=fa[p])
          ct[p]++,vis[p]=i;
          }
      Rsort(mxn);
      for(int i=2,d;i<=tot;i++)
        {d=q[i];ans[d]=ans[fa[d]]+(ct[d]>=k?l[d]-l[fa[d]]:0);}//
      for(int i=1;i<=n;i++)
        {
          ll prn=0;
          for(int lm=len[i],cr=1,j=0;j<lm;j++)
        {
          cr=go[cr][ch[i][j]-'a'+1];
          prn+=ans[cr];
        }
          printf("%lld ",prn);
        }
      puts("");return 0;
    }
    View Code

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2780

    和上一道题一样。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<string>
    using namespace std;
    int const xn=2e5+5;
    const int N=1e4+5,M=2e5+5,N2=4e5+5,K=27;
    int n,go[M][K],fa[M],l[M],ct[M],tot=1;
    string s[N];int len[N],vis[M];
    int cz(int p,int w)
    {
      int q=go[p][w],nq=++tot; l[nq]=l[p]+1;/////////l[p]+1 not l[q]+1!!!!!
      fa[nq]=fa[q];fa[q]=nq;
      memcpy(go[nq],go[q],sizeof go[q]);
      for(;p&&go[p][w]==q;p=fa[p])go[p][w]=nq;
      return nq;
    }
    int ins(int p,int w)
    {
      if(go[p][w])
        {
          int q=go[p][w];
          if(l[q]==l[p]+1)return q; else return cz(p,w);
        }
      else
        {
          int np=++tot;l[np]=l[p]+1;
          for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
          if(!p)fa[np]=1;
          else
        {
          int q=go[p][w];
          if(l[q]==l[p]+1)fa[np]=q; else fa[np]=cz(p,w);
        }
          return np;
        }
    }
    char ch[N2]; int Q;
    int main()
    {
      scanf("%d%d",&n,&Q);
      for(int i=1;i<=n;i++)
        {
          scanf("%s",ch);len[i]=strlen(ch);
          s[i]=(string)ch;
          for(int pr=1,j=0,lm=len[i];j<lm;j++)
        pr=ins(pr,ch[j]-'a'+1);
        }
      for(int i=1;i<=n;i++)
        for(int cr=1,j=0,lm=len[i];j<lm;j++)
          {
        cr=go[cr][s[i][j]-'a'+1];
        for(int p=cr;p>1&&vis[p]!=i;p=fa[p])
          ct[p]++,vis[p]=i;
          }
      while(Q--)
        {
          scanf("%s",ch);int lm=strlen(ch),cr=1;
          for(int j=0;j<lm&&cr;j++)
        cr=go[cr][ch[j]-'a'+1];
          printf("%d
    ",ct[cr]);
        }
      return 0;
    }
    View Code
  • 相关阅读:
    Springboot + Atomikos + Druid + Mysql 实现JTA分布式事务
    JAVA生成一个二维数组,使中间元素不与相邻的9个元素相等,并限制每一个元素的个数
    java.net.UnknownHostException: lc001 未知的网络服务
    Maven 多模块引用版本的问题 java.lang.NoSuchMethodError
    Maven项目运行Junit测试用例 出现ClassNotFound
    CAS5.X 集群配置 初版
    调试CAS源码步骤
    openhtmltopdf 支持自定义字体、粗体
    Java HTML to PDF 支持SVG
    .Net 框架
  • 原文地址:https://www.cnblogs.com/Narh/p/10290569.html
Copyright © 2011-2022 走看看