제출 #1144769

#제출 시각아이디문제언어결과실행 시간메모리
1144769starchanCopy and Paste 3 (JOI22_copypaste3)C++20
57 / 100
3139 ms1050208 KiB
#include<bits/stdc++.h>

#pragma GCC optimize("O3,unroll-loops,fast-math")
#pragma GCC target("avx2,popcnt,bmi,bmi2,lzcnt")
#pragma GCC optimize("Ofast")

using namespace std;
#define int long long
#define in array<int, 2>
#define pb push_back
#define pob pop_back
#define INF (int)1e17
#define fast() ios_base::sync_with_stdio(false); cin.tie(NULL)

const int MX = 3e3;
const int mod1 = 1e9+7;
const int mod2 = 1e9+9;

struct Mpair
{
	int v1, v2;
};

const Mpair b = {37, 31};
const Mpair ib = {621621626, 838709685};


Mpair make(int x)
{
	return {x, x};
}

Mpair operator+(const Mpair& M1, const Mpair& M2)
{
	Mpair ret = M1;
	ret.v1+=M2.v1; (ret.v1)%=mod1;
	ret.v2+=M2.v2; (ret.v2)%=mod2;
	return ret;
}

Mpair operator-(const Mpair& M1, const Mpair& M2)
{
	Mpair ret = M1;
	ret.v1-=M2.v1; ret.v1 += mod1; (ret.v1)%=mod1;
	ret.v2-=M2.v2; ret.v2 += mod2; (ret.v2)%=mod2;
	return ret;
}

Mpair operator*(const Mpair& M1, const Mpair& M2)
{
	Mpair ret = M1;
	ret.v1*=M2.v1; (ret.v1)%=mod1;
	ret.v2*=M2.v2; (ret.v2)%=mod2;
	return ret;
}

in convert(Mpair m)
{
	return {m.v1, m.v2};
}

Mpair ppow[MX];
Mpair ipow[MX];

void pre()
{
	ppow[0] = {1, 1};
	ipow[0] = {1, 1};
	for(int i = 1; i < MX; i++)
	{
		ppow[i] = ppow[i-1]*b;
		ipow[i] = ipow[i-1]*ib;
	}
	return;
}


signed main()
{
	fast(); pre();
	int n, a, b, c; cin >> n;
	vector<int> St(n+1, 0);
	vector<int> S(n+1, 0);
	for(int i = 1; i <= n; i++)
	{
		char xy; cin >> xy;
		St[i] = (xy - 'a' + 1);
		S[n+1-i] = St[i];
	}
	cin >> a >> b >> c;
	vector<Mpair> pref(n+1, {0,0});
	for(int i = 1; i <= n; i++)
		pref[i] = pref[i-1] + make(S[i])*ppow[i];
	
	unordered_map<int, vector<int>> lst;
	
	int forw[n+1][n+1];
	int g[n+1][n+1];
	
	for(int x = 1; x <= n; x++)
	{
		for(int i = 1; i <= n-x+1; i++)
		{
			Mpair hsh = (pref[i+x-1]-pref[i-1])*ipow[i];
			if(lst[hsh.v1].empty())
				lst[hsh.v1].pb(0);
			forw[n+2-(i+x)][x] = lst[hsh.v1].back();
			lst[hsh.v1].pb(i);
			vector<int> C = lst[hsh.v1];
			if((i-1) < x)
			{
				g[(n+2)-(i+x)][x] = n+2-x;
				continue;
			}
			g[(n+2)-(i+x)][x] = (n+2)-(x+C[lower_bound(C.begin(), C.end(), i-x+1)-C.begin()-1]);
		}
		lst.clear();
	}

	vector<array<int, 3>> adj[n+1][n+1];
	for(int x = 1; x <= n; x++)
	{
		for(int i = 1; i <= n+1-x; i++)
		{
			int pl = i; pl = g[pl][x];
			int wt = 0;
			while(pl <= (n+1-x))
			{
				wt++;
				adj[i][pl+x-1].pb({i, i+x-1, (pl-i-wt*x)*a + (wt+1)*c + b});
				pl = g[pl][x];
			}
		}
	}

	int dp[n+1][n+1];

	for(int i = 1; i <= n; i++)
		dp[i][i] = a+b;

	for(int x = 2; x <= n; x++)
	{
		for(int i = 1; i <= (n+1-x); i++)
		{
			dp[i][i+x-1] = min(dp[i+1][i+x-1], dp[i][i+x-2]) + a;
			for(auto [l, r, w]: adj[i][i+x-1])
				dp[i][i+x-1] = min(dp[i][i+x-1], dp[l][r]+w);
		}
	}
	cout << (dp[1][n]-b) << "\n";
	return 0;
}	
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...