题解 CF461E Appleman and a Game
考虑知道了
现在考虑使得每次这个 dp 的转移时的
所以,这个串只和长度、开头、结尾有关。于是我们可以预处理出
但是有可能最后一段不是由一个最短串组成,那么考虑在开头转移时可以只填最短串的一段前缀(即
然后发现这个
而对于前面的
总时间复杂度
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 1e9;
const ll INF = 1e15;
const int N = 1e5;
inline ll read() {
ll s = 0,f = 1;char ch = getchar();
while (!isdigit(ch)) f = ch == '-' ? -1 : 1, ch = getchar();
while (isdigit(ch)) s = (s << 3) + (s << 1) + ch - '0', ch = getchar();
return s*f;
}
int f[N + 10][5],val[4][4],l;
ll n;
string s;
struct Matrix {
ll w[45][45];
ll* operator[] (const int x) {
return w[x];
}
friend Matrix operator * (Matrix x,Matrix y) {
Matrix z;
memset(z.w,-0x3f,sizeof z.w);
for (int i = 0;i < 40;i ++ )
for (int k = 0;k < 40;k ++ )
for (int j = 0;j < 40;j ++ )
z[i][j] = max(z[i][j],x[i][k] + y[k][j]);
return z;
}
}A;
int id(int i,int j) {
return (i - 1) * 4 + j;
}
Matrix qpow(Matrix a,ll b) {
Matrix res;
memset(res.w,0,sizeof res.w);
while (b) {
if (b & 1) res = res * a;
b >>= 1, a = a * a;
}
return res;
}
map<string,int> mp;
int main() {
n = read();
cin >> s;
l = s.size();s = '#' + s;
for (int i = 2;i <= 10;i ++ ) {
for (char a = 'A';a <= 'D';a ++ )
for (char b = 'A';b <= 'D';b ++ ) {
if (val[a - 'A'][b - 'A']) continue;
int ct = 0;
mp.clear();
for (int j = 1;j <= l - i + 1;j ++ )
if (s[j] == a && s[j + i - 1] == b) {
string ss = s.substr(j,i);
if (!mp[ss]) mp[ss] = 1, ct ++;
}
if (ct < pow(4,i - 2)) val[a - 'A'][b - 'A'] = i;
}
}
memset(A.w,-0x3f,sizeof A.w);
for (int i = 0;i < 36;i ++ ) A[i + 4][i] = 0;
for (int j = 0;j < 4;j ++ )
for (int k = 0;k < 4;k ++ ) {
A[id(10 - val[k][j] + 2,k)][id(10,j)] = 1;
}
Matrix ans = qpow(A,n);
ll Ans = max({ans[0][id(10,0)],ans[0][id(10,1)],ans[0][id(10,2)],ans[0][id(10,3)]});
cout << Ans;
return 0;
}