zoukankan      html  css  js  c++  java
  • CF1120 C. Compress String(SAM+DP)

    有方程dp[i]=min(dp[i-1]+A,dp[j]+B);如果s[j+1,i]在s[i,j]中出现,所以我们就是要知道每个子串在s出现的第一个位置,这个可以hash实现或者sam,或者kmp实现。

    pos[i][j]表示s[i,j]对应的sam的位置,occ[],表示第一次出现的位置。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep2(i,a,b) for(int i=a;i>=b;i--)
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=100010;
    char c[maxn],s[maxn];
    struct SAM{
        int ch[maxn][26],fa[maxn],maxlen[maxn],cnt,last;
        int a[maxn],b[maxn],occ[maxn];
        void init()
        {
            cnt=last=1;
            memset(ch[1],0,sizeof(ch[1]));
            memset(occ,0x3f,sizeof(occ));
        }
        int add(int x,int pos)
        {
           int np=++cnt,p=last; last=np;  occ[np]=pos;
           maxlen[np]=maxlen[p]+1;memset(ch[np],0,sizeof(ch[np]));
           while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
           if(!p) fa[np]=1;
           else {
             int q=ch[p][x];
             if(maxlen[q]==maxlen[p]+1) fa[np]=q;
             else {
                int nq=++cnt; maxlen[nq]=maxlen[p]+1;
                fa[nq]=fa[q]; fa[q]=fa[np]=nq;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
             }
           }
        }
        void Sort()
        {
            rep(i,1,cnt) a[i]=0;
            rep(i,1,cnt) a[maxlen[i]]++;
            rep(i,1,cnt) a[i]+=a[i-1];
            rep(i,1,cnt) b[a[maxlen[i]]--]=i;
            for(int i=cnt;i>=1;i--)
                occ[fa[b[i]]]=min(occ[b[i]],occ[fa[b[i]]]);
        }
    }T;
    int a[maxn],A,B,dp[maxn],pos[5010][5010];
    int main()
    {
        int N;
        scanf("%d%d%d%s",&N,&A,&B,c+1);
        T.init();
        rep(i,1,N) T.add(c[i]-'a',i);
        rep(i,1,N) {
            int now=1;
            rep(j,i,N){
                now=T.ch[now][c[j]-'a'];
                pos[i][j]=now;
            }
        }
        T.Sort();
        rep(i,1,N){
            dp[i]=dp[i-1]+A;
            rep(j,1,i-1){
                if(T.occ[pos[j+1][i]]<=j){
                    dp[i]=min(dp[i],dp[j]+B);
                    break;
                }
            }
        }
        printf("%d
    ",dp[N]);
        return 0;
    }
  • 相关阅读:
    折线图平滑
    Matplotlib字体大小设置
    折线图
    柱状图
    zip()函数
    matplotlib基础
    unique()函数
    sorted()与sort()函数
    Oracle数据库文件导出为CSV格式的方法
    Numpy和Pandas
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10468652.html
Copyright © 2011-2022 走看看