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;
}