zoukankan      html  css  js  c++  java
  • hiho# 1465 重复旋律8 循环串计数 后缀自动机

    题目传送门

    题意:给出一个母串,再给出n个串,问对于每个串,母串中有几个子串是可以通过循环变化得到这个串。

    思路:对母串建SAM,求出$right$集。

      把匹配串复制一遍,和母串进行匹配,当匹配长度大于等于$siz$时,将当时的$p$跳到最远的$len$还大于$siz$的父串(不停的往父亲跳),答案加上$right$,然后标记一下,如果标记过的就不加。(因为此时这个p是唯一的,不会被重复计算)

    #include<bits/stdc++.h>
    #define clr(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const ll mod=1e9+7;
    const int maxn=200010;
    char s[maxn];
    int len[maxn<<1],ch[maxn<<1][27],fa[maxn<<1],tot=1,root=1,last=1,siz,r[maxn<<1],vis[maxn<<1];
    int a[maxn<<1],c[maxn<<1],ans[maxn<<1];
    ll dp[maxn<<1];
    void extend(int x){
        int now=++tot,pre=last;
        r[now]=1;
        last=now,len[now]=len[pre]+1;
        while( pre && !ch[pre][x]){
            ch[pre][x]=now;
            pre=fa[pre];
        }
        if(!pre)fa[now]=root;
        else{
            int q = ch[pre][x];
            if(len[q]==len[pre]+1)fa[now]=q;
            else {
                int nows=++tot;
                memcpy(ch[nows],ch[q],sizeof(ch[q]));
                len[nows]=len[pre]+1;
                fa[nows]=fa[q];
                fa[q]=fa[now]=nows;
                while(pre&&ch[pre][x]==q){
                    ch[pre][x]=nows;
                    pre=fa[pre];
                }
            }
        }
    }
    void topSort(){
        for(int i=1;i<=tot;i++)c[len[i]]++;
        for(int i=1;i<=tot;i++)c[i]+=c[i-1];
        for(int i=tot;i>0;i--)a[c[len[i]]--]=i;
        for(int i=tot;i>0;i--)r[fa[a[i]]]+=r[a[i]];
    }
    int cal(int p,int inx){
        while(fa[p]&&len[fa[p]]>=siz)p=fa[p];
        return vis[p]==inx?0:(vis[p]=inx,r[p]);
    }
    int main(){
        scanf("%s",s);
        siz=strlen(s);
        for(int i=0;i<siz;i++){
            int p=s[i]-'a';
            extend(p);
        }
        topSort();
        int n;
        cin>>n;
        int index=1;
        while(n--){
            scanf("%s",s);
            siz=strlen(s);
            for(int i=0;i<siz;i++)
            {
                s[i+siz]=s[i];
            }
            int cur=1,maxx=0;
            ll ans=0;
            for(int i=0;i<(siz<<1);i++)
            {
                int p=s[i]-'a';
                if(ch[cur][p]){
                    maxx++;
                    cur=ch[cur][p];
                }else{
                    while(cur&&ch[cur][p]==0)cur=fa[cur];
                    if(cur){
                        maxx=len[cur]+1;
                        cur=ch[cur][p];
                    }else{
                        maxx=0;
                        cur=1;
                    }
                }
                if(maxx>=siz)ans+=cal(cur,index);
            }
            index++;
            printf("%lld
    ",ans);
        }
    
    }
  • 相关阅读:
    String字符串性能优化的探究
    Spring笔记(5)
    Spring笔记(4)
    力扣217. 存在重复元素
    力扣1480. 一维数组的动态和
    Ribbon 和 Feign 的区别
    Eureka的自我保护机制
    Planar graph and map 3-colorability reduce to one another
    3-colorability
    一少年独坐屋中突然顿悟!-回溯
  • 原文地址:https://www.cnblogs.com/mountaink/p/10666563.html
Copyright © 2011-2022 走看看