• codeforces 235C. Cyclical Quest(后缀自动机)


    传送门

    解题思路:

    既然是询问循环字符串出现次数,那么第一步当然是要倍长。

    注意这里的贡献最好在广义后缀自动机中跑一遍匹配。

    注意一定要一直控制其长度否则会出现前段失配现象导致算了不该算的。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 typedef long long lnt;
      5 struct sant{
      6     int tranc[26];
      7     int len;
      8     int pre;
      9 }s[2000000];
     10 struct pnt{
     11     lnt wgt;
     12     int vis;
     13 }p[2000000];
     14 struct ent{
     15     int twd;
     16     int lst;
     17 }e[2000000];
     18 int cnt;
     19 int fin;
     20 int siz;
     21 int n,Q;
     22 int has[2000000];
     23 int topo[2000000];
     24 char tmp[2000000];
     25 void Insert(int c)
     26 {
     27     int nwp,nwq,lsp,lsq;
     28     nwp=++siz;
     29     s[nwp].len=s[fin].len+1;
     30     p[nwp].wgt=1;
     31     for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
     32         s[lsp].tranc[c]=nwp;
     33     if(!lsp)
     34         s[nwp].pre=1;
     35     else{
     36         lsq=s[lsp].tranc[c];
     37         if(s[lsq].len==s[lsp].len+1)
     38             s[nwp].pre=lsq;
     39         else{
     40             nwq=++siz;
     41             s[nwq]=s[lsq];
     42             s[nwq].len=s[lsp].len+1;
     43             s[lsq].pre=s[nwp].pre=nwq;
     44             while(s[lsp].tranc[c]==lsq)
     45             {
     46                 s[lsp].tranc[c]=nwq;
     47                 lsp=s[lsp].pre;
     48             }
     49         }
     50     }
     51     fin=nwp;
     52     return ;
     53 }
     54 int main()
     55 {
     56     fin=++siz;
     57     scanf("%s",tmp+1);
     58     int len=strlen(tmp+1);
     59     for(int i=1;i<=len;i++)
     60         Insert(tmp[i]-'a');
     61     for(int i=1;i<=siz;i++)
     62         has[s[i].len]++;
     63     for(int i=1;i<=len;i++)
     64         has[i]+=has[i-1];
     65     for(int i=1;i<=siz;i++)
     66         topo[has[s[i].len]--]=i;
     67     for(int i=siz;i;i--)
     68     {
     69         int x=topo[i];
     70         p[s[x].pre].wgt+=p[x].wgt;
     71     }
     72     scanf("%d",&Q);
     73     while(Q--)
     74     {
     75         scanf("%s",tmp);
     76         len=strlen(tmp);
     77         int ln=len<<1;
     78         lnt ans=0;
     79         int root=1,l=0;
     80         for(int j=0;j<ln;j++)
     81         {
     82             int i=j%len;
     83             int c=tmp[i]-'a';
     84             while(root&&!s[root].tranc[c])
     85                 root=s[root].pre,l=s[root].len;
     86             root=s[root].tranc[c];
     87             if(!root)
     88                 root=1,l=0;
     89             else{
     90                 l++;
     91                 while(s[s[root].pre].len>=len&&s[root].pre)
     92                     root=s[root].pre,l=s[root].len;
     93                 if(p[root].vis!=Q+1&&l>=len)
     94                 {
     95                     ans+=p[root].wgt;
     96                     p[root].vis=Q+1;
     97                 }
     98             }
     99         }
    100         printf("%I64d
    ",ans);
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    使用rails Devise
    (转)两年服务器开发的一句话经验集
    新版本,新起点。
    学习《锋利的jQuery》1
    Watir 使用
    一些Web Front的收集
    PHP日期时间函数的高级应用技巧
    如何防止动态加载JavaScript引起的内存泄漏问题
    JavaScript常用函数库详解
    JavaScript加密解密
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10083930.html
Copyright © 2020-2023  润新知