HDU5470 Typewriter SAM 动态规划 单调队列

原文链接https://www.cnblogs.com/zhouzhendong/p/HDU5470.html

题目传送门 - HDU5470

题意

题解

  太晚了,先鸽一鸽。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
int T,n,Case=0;
int R[N],c[26],A,B;
int Time[N<<1],tax[N],id[N<<1];
char s[N];
LL dp[N],v[N],q[N],head,tail;
struct SAM{
	int Next[26],fa,Max;
}t[N<<1];
int size;
void init(){
	memset(t,0,sizeof t);
	memset(Time,63,sizeof Time);
	size=1,t[0].Max=-1;
	for (int i=0;i<26;i++)
		t[0].Next[i]=1;
}
int extend(int p,int c){
	if (t[p].Next[c]&&t[p].Max+1==t[t[p].Next[c]].Max)
		return t[p].Next[c];
	int np=++size,q,nq;
	t[np].Max=t[p].Max+1;
	for (;!t[p].Next[c];p=t[p].fa)
		t[p].Next[c]=np;
	q=t[p].Next[c];
	if (t[p].Max+1==t[q].Max)
		t[np].fa=q;
	else {
		nq=++size;
		t[nq]=t[q],t[nq].Max=t[p].Max+1;
		t[np].fa=t[q].fa=nq;
		for (;t[p].Next[c]==q;p=t[p].fa)
			t[p].Next[c]=nq;
	}
	return np;
}
void Get_Time(){
	memset(tax,0,sizeof tax);
	for (int i=1;i<=size;i++)
		tax[t[i].Max]++;
	for (int i=1;i<=n;i++)
		tax[i]+=tax[i-1];
	for (int i=1;i<=size;i++)
		id[tax[t[i].Max]--]=i;
	for (int i=size;i>1;i--)
		Time[t[id[i]].fa]=min(Time[t[id[i]].fa],Time[id[i]]);
}
int main(){
	scanf("%d",&T);
	while (T--){
		scanf("%s",s+1);
		n=strlen(s+1);
		init();
		for (int i=1,p=1;i<=n;i++)
			Time[p=extend(p,s[i]-'a')]=i;
		Get_Time();
		for (int i=0;i<26;i++)
			scanf("%d",&c[i]);
		scanf("%d%d",&A,&B);
		for (int i=1,j=0,p=1,len=0;i<=n;i++){
			while (1){
				int Next=t[p].Next[s[j+1]-'a'];
				while (!(Next&&Time[Next]<i)&&j-t[t[p].fa].Max<i)
					p=t[p].fa,len=t[p].Max,Next=t[p].Next[s[j+1]-'a'];
				if (Next&&Time[Next]<i)
					j++,p=Next;
				else
					break;
			}
			R[i]=j;
		}
		head=1,tail=0;
		memset(q,0,sizeof q);
		dp[0]=0;
		for (int i=1;i<=n;i++){
			dp[i]=dp[i-1]+c[s[i]-'a'];
			while (head<=tail&&R[q[head]+1]<i)
				head++;
			if (head<=tail)
				dp[i]=min(dp[i],v[q[head]]+1LL*A*i+B*2);
			v[i]=dp[i]-1LL*A*i;
			if (R[i+1]>i){
				while (head<=tail&&v[i]<=v[q[tail]])
					tail--;
				q[++tail]=i;
			}
		}
		printf("Case #%d: %lld\n",++Case,dp[n]);
	}
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/zhouzhendong/p/HDU5470.html