• BZOJ3676 APIO2014回文串(manacher+后缀自动机)


      由于本质不同的回文子串数量是O(n)的,考虑在对于每个回文子串在第一次找到它时对其暴力统计。可以发现manacher时若右端点移动则找到了一个新回文串。注意这样会漏掉串长为1的情况,特判一下。

      现在问题变为统计一个子串的出现次数。可以用SA,二分乱搞一下即可。这里使用SAM。以parent树上表示该子串的节点为起点,用倍增往上跳,找到深度最小的满足len限制的点就好了,出现次数就是其right集合的大小。

      uojAC,luoguRE一个点,bzojMLE……

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 600010
    int n,last,cnt,len[N],fail[N],son[N][26],size[N],pos[N>>1],p[N];
    long long ans=0;
    char s[N];
    namespace tree
    {
        int p[N],t=0,fa[N][20];
        struct data{int to,nxt;
        }edge[N];
        void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
        void dfs(int k)
        {
            for (int i=p[k];i;i=edge[i].nxt)
            {
                fa[edge[i].to][0]=k;
                dfs(edge[i].to);
                size[k]+=size[edge[i].to];
            }
        }
        void build()
        {
            for (int i=2;i<=cnt;i++) addedge(fail[i],i);
            fa[1][0]=1;dfs(1);
            for (int j=1;j<20;j++)
                for (int i=1;i<=cnt;i++)
                fa[i][j]=fa[fa[i][j-1]][j-1];
        }
        int calc(int l,int r)
        {
            int x=pos[r];
            for (int j=19;~j;j--) if (len[fa[x][j]]>=r-l+1) x=fa[x][j];
            return size[x];
        }
    }
    using tree::calc;
    void ins(int c,int n)
    {
        int x=++cnt,p=last;last=x;len[x]=n;size[x]=1;pos[n]=x;
        while (!son[p][c]&&p) son[p][c]=x,p=fail[p];
        if (!p) fail[x]=1;
        else
        {
            int q=son[p][c];
            if (len[p]+1==len[q]) fail[x]=q;
            else
            {
                int y=++cnt;len[y]=len[p]+1;
                memcpy(son[y],son[q],sizeof(son[q]));
                fail[y]=fail[q];fail[q]=fail[x]=y;
                while (son[p][c]==q) son[p][c]=y,p=fail[p];
            }
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3676.in","r",stdin);
        freopen("bzoj3676.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        last=cnt=1;
        scanf("%s",s+1);n=strlen(s+1);
        for (int i=1;i<=n;i++) ins(s[i]-97,i);
        tree::build();
        for (int i=n;i>=1;i--) s[i*2-1]=s[i];
        for (int i=1;i<n;i++) s[i<<1]='$';
        int x=1;
        for (int i=1;i<=n;i++) ans=max(ans,1ll*calc(i,i));
        for (int i=2;i<n*2;i++) 
        {
            if (x+p[x]>i) p[i]=min(x+p[x]-i,p[x-(i-x)]);
            while (i-p[i]-1>=1&&i+p[i]+1<n*2&&s[i+p[i]+1]==s[i-p[i]-1]) 
            {
                p[i]++;
                if (s[i+p[i]]!='$') ans=max(ans,1ll*((i+p[i]>>1)-(i-p[i]>>1)+1)*calc((i-p[i]>>1)+1,(i+p[i]>>1)+1));
            }
            if (i+p[i]>x+p[x]) x=i;
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    (论文笔记Arxiv2021)Walk in the Cloud: Learning Curves for Point Clouds Shape Analysis
    论文笔记:(2021CVPR)PAConv: Position Adaptive Convolution with Dynamic Kernel Assembling on Point Clouds
    K-Fold 交叉验证
    Elsevier(爱思唯尔)期刊模板的使用
    LATEX学习和IEEE Tran模板介绍
    MAP使用containsKey和containsValue方法,验证键值对是否存在此KEY或VAL值
    1、c#中解析json 文件的方法:
    java 多线程
    python 骚操作 输入日期年获取全年所有日期输入年月获取整月日期
    Django 项目 钉钉群消息预警
  • 原文地址:https://www.cnblogs.com/Gloid/p/9527580.html
Copyright © 2020-2023  润新知