zoukankan      html  css  js  c++  java
  • hiho一下第131周 后缀自动机二·重复旋律8(循环相似子串)

    后缀自动机五·重复旋律8

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

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

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

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

    解题方法提示

    输入

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

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

    输出

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

    样例输入
    abac
    3
    a
    ab
    ca
    样例输出
    2
    2
    1
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <time.h>
    #include <string>
    #include <map>
    #include <stack>
    #include <vector>
    #include <set>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int N=4e6+100;
    const int M=1e6+5;
    const long long MOD = 1000000007LL;
    int tot,slink[2*N],trans[2*N][26],minlen[2*N],maxlen[2*N],edpts[2*N];
    string str;
    int n,sz_end[N*2];
    int containPrefix[N],ind[N],ans[2*N+10],cnt[N*2],green[2*N];
    ll sum[N*2],sz_valid[N*2];
    int newstate(int _maxlen,int _minlen,int* _trans,int _slink,int _green) {
        maxlen[++tot]=_maxlen;
        minlen[tot]=_minlen;
        slink[tot]=_slink;
        green[tot]=_green;
        if(_trans)
            for(int i=0; i<26; i++)
                trans[tot][i]=_trans[i];
        return tot;
    }
    int add_char(char ch,int u) {
        int c=ch-'a',v=u;
        int z=newstate(maxlen[u]+1,-1,NULL,0,1);
        containPrefix[z]=1;
        while(v&&!trans[v][c]) {
            trans[v][c]=z;
            v=slink[v];
        }
        if(!v) {
            minlen[z]=1;
            slink[z]=1;
            ind[0]++;
            return z;
        }
        int x=trans[v][c];
        if(maxlen[v]+1==maxlen[x]) {
            slink[z]=x;
            minlen[z]=maxlen[x]+1;
            ind[x]++;
            return z;
        }
        int y=newstate(maxlen[v]+1,-1,trans[x],slink[x],0);
        slink[z]=slink[x]=y;
        ind[y]+=2;
        minlen[x]=minlen[z]=maxlen[y]+1;
        while(v&&trans[v][c]==x) {
            trans[v][c]=y;
            v=slink[v];
        }
        minlen[y]=maxlen[slink[y]]+1;
        return z;
    }
    void init_dag() {
        for ( int i = 0; i <=tot; i++ ) {
            if(slink[i]>0)cnt[slink[i]]++;
        }
    }
    
    void topsort() {
        queue<int>q;
        for ( int i = 1; i <=tot; i++ ) {
            if ( cnt[i] == 0 ) {
                q.push(i);
                sz_valid[i] = 1;
                sum[i] = 0;
            }
        }
        while(!q.empty()) {
            int i=q.front();
            q.pop();
            if(green[i])sz_end[i]++;
            int j=slink[i];
            sz_end[j]+=sz_end[i];
            if(!(--cnt[j]))q.push(j);
        }
    }
    int solve() {
        vector<bool> visited(N*2,false);
        int res = 0;
        string t;
        cin>>t;
        int len = t.size();
        for(int i = 0; i < len-1; i++) {
            t+= t[i];
        }
        int len2 = len*2-1;
        int u,l;
        u = 1;
        l = 0;
        for(int i = 0; i < len2; i++) {
            int c = t[i] - 'a';
            for(; u!=1 && trans[u][c]==0;) {
                u = slink[u];
                l = maxlen[u];
            }
            if(trans[u][c] >0) {
                u = trans[u][c];
                l = l + 1;
            } else {
                u = 1;
                l = 0;
            }
            if(l > len) {
                for(; maxlen[slink[u]] >= len;) {
                    u = slink[u];
                    l = maxlen[u];
                }
            }
            if(l >= len && !visited[u]) {
                visited[u] = true;
                res += sz_end[u];
            }
        }
        return res;
    }
    int main() {
        cin>>str;
        cin>>n;
        int pre=1;
        tot=1;
        int len=str.length();
        for(int i=0; i<len; i++) {
            pre=add_char(str[i],pre);
        }
        init_dag();
        topsort();
        for(int i=0;i<n;i++){
            printf("%d
    ",solve());
        }
        return 0;
    }
  • 相关阅读:
    【python】为什么IDE看很多源码的函数都是pass带过
    【PyQt5】使用pyqtgraph绘图时UI卡顿的解决
    Qt designer button图标适应控件大小
    【转载】标量,向量,矩阵与张量
    Python实现简单的HTTP服务器(支持文件下载)
    Python——Pygame实现生命游戏(game of life)
    mysql允许外部连接设置
    fastdfs在ubuntu的编译安装,php扩展fastdfs的安装
    ubuntu下安装mongodb
    ubuntu16.04安装mongo扩展出现的问题
  • 原文地址:https://www.cnblogs.com/jianrenfang/p/6347843.html
Copyright © 2011-2022 走看看