题意:给定一个由小写字母组成的字符串,每次可以花费p在串后加上任意一个字母,花费q在串后复制一个当前串的子串,问生成字符串的最小花费

n<=2e5,1<=p,q<2^31

思路:

 SAM上每个结点表示的串长度为[st[F[p]]+1,st[p]],如果长度不符合当前i,j的要求,比如复制的时候长度小于当前的一半或者长度大于[j+1,i]就暴力往上跳parent

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 typedef pair<ll,int>P;
 11 #define N  500010
 12 #define M  210000
 13 #define fi first
 14 #define se second
 15 #define MP make_pair
 16 #define pi acos(-1)
 17 #define mem(a,b) memset(a,b,sizeof(a))
 18 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 19 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 20 #define lowbit(x) x&(-x)
 21 #define Rand (rand()*(1<<16)+rand())
 22 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 23 #define ls p<<1
 24 #define rs p<<1|1
 25
 26 const ll MOD=1e9+7,inv2=(MOD+1)/2;
 27       double eps=1e-6;
 28       ll INF=1ll<<62;
 29       ll inf=5e13;
 30       int dx[4]={-1,1,0,0};
 31       int dy[4]={0,0,-1,1};
 32
 33 char s[N];
 34 int ch[N][26],st[N],F[N],p,np,q,nq,cnt,t;
 35 ll dp[N],A,B;
 36
 37 int read()
 38 {
 39    int v=0,f=1;
 40    char c=getchar();
 41    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 42    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 43    return v*f;
 44 }
 45
 46 struct sam
 47 {
 48     void extend(int x)
 49     {
 50         p=np;
 51         st[np=++cnt]=st[p]+1;
 52         while(p&&!ch[p][x])
 53         {
 54             ch[p][x]=np;
 55             p=F[p];
 56         }
 57
 58         if(!p) F[np]=1;
 59           else if(st[p]+1==st[q=ch[p][x]]) F[np]=q;
 60             else
 61             {
 62                   st[nq=++cnt]=st[p]+1;
 63                   memcpy(ch[nq],ch[q],sizeof ch[q]);
 64                   F[nq]=F[q];
 65                   F[q]=F[np]=nq;
 66                   while(p&&ch[p][x]==q)
 67                   {
 68                       ch[p][x]=nq;
 69                       p=F[p];
 70                   }
 71             }
 72     }
 73
 74     void cancel(int len)
 75     {
 76         while(t&&st[F[t]]>=len) t=F[t];
 77         if(!t) t=1;
 78     }
 79
 80     void trans(int len,int x)
 81     {
 82         t=ch[t][x];
 83         if(!t) t=1;
 84         cancel(len);
 85     }
 86
 87 }sam;
 88
 89 void solve()
 90 {
 91     int n=strlen(s);
 92     //rep(i,1,n) dp[i]=INF;
 93
 94     cnt=np=t=1;
 95     sam.extend(s[0]-'a');
 96     dp[0]=A;
 97     int j=1;
 98     rep(i,1,n-1)
 99     {
100         dp[i]=dp[i-1]+A;
101         int x=s[i]-'a';
102         while((!ch[t][x]||i-j+1>(i+1)/2)&&j<=i)
103         {
104             sam.extend(s[j++]-'a');
105             sam.cancel(i-j);
106
107         }
108         sam.trans(i-j+1,x);
109         if(j<=i) dp[i]=min(dp[i],dp[j-1]+B);
110     }
111
112     rep(i,1,cnt)
113     {
114         rep(j,0,25) ch[i][j]=0;
115         F[i]=st[i]=0;
116     }
117     printf("%lld\n",dp[n-1]);
118 }
119
120 int main()
121 {
122     //freopen("1.in","r",stdin);
123     //freopen("1.out","w",stdout);
124     while(scanf("%s%lld%lld",s,&A,&B)!=EOF)
125     {
126         solve();
127     }
128     return 0;
129 }
02-14 03:57