zoukankan      html  css  js  c++  java
  • BZOJ 2882 工艺 ——后缀自动机 最小表示法

    先说后缀自动机的做法。

    直接把S串复制一遍成SS,然后建立后缀自动机,go边相当于在当前字符的后面插入,而son边可以看作在字符串前面加一个字符。

    所以贪心的走字典序最小的边即可,而且根据后缀自动机的构建的性质,是一定可以走够len的,然后输出即可。

    人生第一个后缀自动机的代码。

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<map>
    #include<cstdio>
    #define N 600003
    using namespace std;
    int n,m,cnt,nq,np,p,q,last,root;
    map<int,int> ch[N*2];
    int fa[N*2],l[N*2],a[N];
    void extend(int x)
    {
        int c=a[x];
        p=last; np=++cnt; last=np;
        l[np]=x;
        for (;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
        if (!p) fa[np]=root;
        else {
            q=ch[p][c];
            if (l[q]==l[p]+1) fa[np]=q;
            else {
                nq=++cnt; l[nq]=l[q]+1;
                ch[nq]=ch[q];
                fa[nq]=fa[q];
                fa[q]=fa[np]=nq;
                for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        for (int i=1;i<=n;i++) a[n+i]=a[i];
        m=2*n;
        last=root=++cnt; ch[N].clear();
        for (int i=1;i<=m;i++) extend(i);
        p=1;
        map<int,int>::iterator t;
        for (int i=1;i<=n;i++) {
            t=ch[p].begin();
            p=t->second;
            if (i!=n) printf("%d ",t->first);
            else printf("%d
    ",t->first);
        }
    }
    

    然后再来说说最小表示法,大概的思想就是用两个指针来比较,然后不相等的时候就会排除很大的一片区间,然后最后剩下的就是最优解,最大表示法同理,写完后跑的飞快。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define maxn 300005
    int n,a[maxn],pos;
     
    int main()
    {
        scanf("%d",&n);
        F(i,1,n) scanf("%d",&a[i]);
        int i=1,j=2,k=0,flag=0;
        while (i<=n&&j<=n)
        {
            k=0;
    //      printf("%d %d
    ",i,j); 
            while (a[(i+k-1)%n+1]==a[(j+k-1)%n+1]&&k<=n) k++;
            if (k==n) {pos=i;flag=1;}
            else
            {
                if (a[(i+k-1)%n+1]>a[(j+k-1)%n+1])
                {
                    if (i+k+1<=j) i=j+1;
                    else i=i+k+1;
                }
                else
                {
                    if (j+k+1<=i) j=i+1;
                    else j=j+k+1;
                }
            }
        }
        if (!flag) pos=min(i,j);
        F(i,1,n) printf("%d%c",a[(pos+i-2)%n+1],i==n?'
    ':' ');
    }
    

      

  • 相关阅读:
    数据处理
    Interleaving String
    Distinct Subsequences
    caffe 输入图像图像加高斯噪声
    caffe resize用interpolation
    软件測试基本方法(七)之验收測试
    CSS入门学习
    bzoj1458 士兵占据
    Swift高阶函数介绍(闭包、Map、Filter、Reduce)
    每天一点儿Java--list
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6486717.html
Copyright © 2011-2022 走看看