zoukankan      html  css  js  c++  java
  • hihocoder 后缀自动机五·重复旋律8 求循环同构串出现的次数

    描述

    小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一段音乐旋律可以被表示为一段数构成的数列。

    小Hi发现旋律可以循环,每次把一段旋律里面最前面一个音换到最后面就成为了原旋律的“循环相似旋律”,还可以对“循环相似旋律”进行相同的变换能继续得到原串的“循环相似旋律”。

    小Hi对此产生了浓厚的兴趣,他有若干段旋律,和一部音乐作品。对于每一段旋律,他想知道有多少在音乐作品中的子串(重复便多次计)和该旋律是“循环相似旋律”。

    解题方法提示

    输入

    第一行,一个由小写字母构成的字符串S,表示一部音乐作品。字符串S长度不超过100000。

    第二行,一个整数N,表示有N段旋律。接下来N行,每行包含一个由小写字母构成的字符串str,表示一段旋律。所有旋律的长度和不超过 100000。

    输出

    输出共N行,每行一个整数,表示答案。

    Sample Input

    abac
    3
    a
    ab
    ca

    Sample Output

    2
    2
    1

    一个endpos只能被寻找到一次
      1 #pragma GCC optimize(2)
      2 #pragma G++ optimize(2)
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cmath>
      6 #include<iostream>
      7 #include<algorithm>
      8 #include<queue>
      9 
     10 #define ll long long
     11 #define N 300007
     12 using namespace std;
     13 inline int read()
     14 {
     15     int x=0,f=1;char ch=getchar();
     16     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
     17     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
     18     return x*f;
     19 }
     20 
     21 int n;
     22 struct sam
     23 {
     24     int cnt,last;
     25     int c[N][26],fa[N],mx[N],endpos[N];
     26     sam(){cnt=last=1;}
     27     void extend(int x)
     28     {
     29         int p=last,np=last=++cnt;mx[np]=mx[p]+1;endpos[np]=1;
     30         while(p&&!c[p][x])
     31         {
     32             c[p][x]=np;
     33             p=fa[p];
     34         }
     35         if(!p)fa[np]=1;
     36         else
     37         {
     38             int q=c[p][x];
     39             if(mx[q]==mx[p]+1)fa[np]=q;
     40             else
     41             {
     42                 int nq=++cnt;mx[nq]=mx[p]+1;
     43                 memcpy(c[nq],c[q],sizeof(c[q]));
     44                 fa[nq]=fa[q];
     45                 fa[q]=fa[np]=nq;
     46                 while(c[p][x]==q)c[p][x]=nq,p=fa[p];
     47             }
     48         }
     49     }
     50     int now=1,pre=0,du[N];queue<int>q[2];
     51     void init_endpos()
     52     {
     53         for (int i=1;i<=cnt;i++)
     54             if(fa[i])du[fa[i]]++;
     55         for (int i=1;i<=cnt;i++)
     56             if(!du[i])q[pre].push(i);
     57         while(!q[pre].empty())
     58         {
     59             while(!q[pre].empty())
     60             {
     61                 int x=q[pre].front();q[pre].pop();
     62                 endpos[fa[x]]+=endpos[x];
     63                 du[fa[x]]--;
     64                 if(!du[fa[x]])q[now].push(fa[x]);
     65             }
     66             swap(now,pre);
     67         }
     68     }
     69     int u=1,l=0;ll ans;
     70     bool flag[N];
     71     void dp(int x,int n)
     72     {
     73         while(u&&!c[u][x])u=fa[u],l=mx[u];
     74         if(!u)u=1,l=0;
     75         else u=c[u][x],l++;
     76         if(l>n)while(mx[fa[u]]>=n)u=fa[u],l=mx[u];
     77         if(l>=n&&!flag[u])
     78         {
     79             flag[u]=true;
     80             ans+=endpos[u];
     81         }
     82     }
     83     void init()
     84     {
     85         printf("%lld
    ",ans);
     86         ans=0,u=1,l=0;
     87         memset(flag,0,sizeof(flag));
     88     }
     89 }sam;
     90 char s[N],T[N];
     91 
     92 int main()
     93 {
     94     scanf("%s",s+1);int len=strlen(s+1);
     95     for (int i=1;i<=len;i++)sam.extend(s[i]-'a');
     96     sam.init_endpos();
     97     n=read();
     98     while(n--)
     99     {
    100         scanf("%s",T+1);
    101         len=strlen(T+1);
    102         for (int i=1;i<=len;i++)
    103             T[i+len]=T[i];
    104         len=len*2-1;
    105         for (int i=1;i<=len;i++)
    106             sam.dp(T[i]-'a',(len+1)/2);
    107         sam.init();
    108     }
    109 }
  • 相关阅读:
    android修改debug keystore文件使之和正式keystore sha1一致
    scrollView中可以自由滚动的listview
    android gradle的全局管理
    OpenGL学习笔记(三)
    OpenGL学习笔记(二)
    OpenGL学习笔记(一)
    Java编程代码规范中值得留意的地方
    mac上编译Android的arm64位ffmpeg
    入门程序员必读的10本经典书单
    [Android文档翻译]设备兼容性
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8531069.html
Copyright © 2011-2022 走看看