HDU Typewriter 6583 dp SAM 卡常

LINK:Typewriter

好久没写SAM了 什么都给忘了.

写了大概2h.感觉被卡常还看了题解.

考虑dp 然后容易想到维护前面的一个j决策 尽可能小.

然后每次考虑向后加一个字符 不过不行就跳父亲.

我的做法是先建立SAM 然后每个点维护right集中最小的就可以维护决策了.

常数大的很.

考虑不这样做 边建SAM边做dp.

然后每次维护指针j 如果now接不上下个字符 j就向后移动.

注意跳父亲 值得注意的是跳父亲需要写while 大概是因为可能会分裂的缘故。

这个点在没分裂之前是可以直接跳到那个父亲的 分裂之后需要跳两次 而且此时要>=

这一点我始终没想到 最后才看出来 SAM还得多刷几道题来巩固一下 自己有的时候的思维漏洞.

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 1000000000
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 1000000007
#define len(x) t[x].len
#define f(x) t[x].fa
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    RE int x=0,f=1;RE char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;

}
const int MAXN=200010<<1;
int p,q,n,last,cnt;
char a[MAXN];
struct wy
{
    int fa,len;
    int ch[26];
}t[MAXN];
ll f[MAXN];
inline void insert(int x)
{
    int p=last;
    int np=last=++cnt;
    len(np)=len(p)+1;
    while(p&&!t[p].ch[x])
    {
        t[p].ch[x]=np;
        p=f(p);
    }
    if(!p)f(np)=1;
    else
    {
        int q=t[p].ch[x];
        if(len(q)==len(p)+1)f(np)=q;
        else
        {
            int nq=++cnt;
            t[nq]=t[q];
            len(nq)=len(p)+1;
            f(q)=f(np)=nq;
            while(p&&t[p].ch[x]==q)
            {
                t[p].ch[x]=nq;
                p=f(p);
            }
        }
    }
}
int main()
{
    //freopen("1.in","r",stdin);
    while(~scanf("%s",a+1))
    {
        n=strlen(a+1);last=cnt=1;
        gt(p);gt(q);
        int now=1,j=1;insert(a[1]-'a');f[1]=p;
        rep(2,n,i)
        {
            f[i]=f[i-1]+p;
            int cc=a[i]-'a';
            while(1)
            {
                if(t[now].ch[cc])
                {
                    now=t[now].ch[cc];
                    if(i==j)now=1;
                    break;
                }
                insert(a[++j]-'a');
                while(now!=1&&len(f(now))>=i-j-1)
                {
                    now=f(now);
                }
            }
            f[i]=min(f[i],f[j]+q);
        }
        putl(f[n]);
        rep(1,cnt,i)t[i]=t[0];
    }
    return 0;
}
posted @ 2020-07-25 23:09  chdy  阅读(104)  评论(0编辑  收藏  举报