stars 题解
Solution
我们考虑如何判定一个序列是否合法,可以看出的是,我们可以枚举每个排列,如果当前我们构造的 K 失配了,那么我们就把排列中的下一位设为失配的该位值即可。如果存在一个排列使得可以走完整个序列,这个序列即为合法。
我们考虑设 \(f_{i,S}\) 表示的是第 \(i\) 位排列(或是排列的一个前缀)为 \(S\) 能够匹配到的最大长度下的失配点。考虑 \(f_{i,S}\) 以及 \(f_{i+1,S[1:]}\) 的关系。可以发现,对于第一个失配点使得 \(a_{k,S[0]}=a_{i,S[0]}\),那么我们设把 \(S[0]\) 插入 \(k\) 对应的排列位置前面为 \(T\),则有 \(f_{i,S}=\{i,f_{i+1,T}\}\),最大长度显然 \(+1\)。如果找不到,那么我们如果第一个无法匹配的 \(k\) 满足 \(a_{k,S[0]}=a_{i,S[0]}\),那么我们设把 \(S[0]\) 放在最后的排列为 \(T\),则有 \(f_{i,S}=\{i,f_{i+1,T}\}\),最大长度显然 \(+1\),不行的话,则有 \(f_{i,S}=\{i,f_{i+1,S[1:]}\}\)。
复杂度我实现的很丑,据说可以做到 \(\Theta(nk!)\),这里代码放上来仅供参考吧。
Code
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define MAXN 100005
#define MAXM 605
#define MAXK 7
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}
int N,K,cnt,ind[MAXN],a[MAXN][MAXK],val[MAXN][MAXM],nxt[MAXN][MAXK];
#define poly vector<int>
map <poly,int> mp;
map <int,poly> tur;
poly f[2][MAXM];
signed main(){
read (N,K);
for (Int i = 1;i <= N;++ i)
for (Int j = 1;j <= K;++ j) read (a[i][j]);
for (Int i = 1;i <= K;++ i) ind[i] = i;
do{
poly S;
for (Int i = 1;i <= K;++ i) S.push_back (ind[i]),tur[++ cnt] = S,mp[S] = cnt;
}while (next_permutation (ind + 1,ind + K + 1));
for (Int i = N;i >= 1;-- i)
for (Int j = 1;j <= K;++ j)
if (a[i][j] == a[i + 1][j]) nxt[i][j] = nxt[i + 1][j];
else nxt[i][j] = i;
int ans = 0;
for (Int i = N;i >= 1;-- i){
for (Int s = 1;s <= cnt;++ s){
f[i & 1][s].clear (),val[i & 1][s] = 0;
poly P = tur[s],T = tur[s],H;T.erase (T.begin());
if (i == N){
f[i & 1][s].push_back (i),val[i & 1][s] = 1;
continue;
}
if (P.size() == 1){
f[i & 1][s].push_back (i),val[i & 1][s] = nxt[i][P[0]] - i + 1;
continue;
}
int nt = mp[T],fuc = -1;bool flg = 0;
for (Int k = 0;k < f[i + 1 & 1][nt].size();++ k){
int pos = f[i + 1 & 1][nt][k];
if (a[pos][P[0]] == a[i][P[0]]){
H.push_back (P[0]),fuc = pos;
for (Int k1 = k;k1 < T.size();++ k1) H.push_back (T[k1]);
flg = 1;
break;
}
H.push_back (T[k]);
}
if (flg){
f[i & 1][s].push_back (i);int sht = mp[H];
for (Int v : f[i + 1 & 1][sht]) if (v != fuc) f[i & 1][s].push_back (v);
val[i & 1][s] = val[i + 1 & 1][sht] + 1;
}
else{
f[i & 1][s].push_back (i);
for (Int v : f[i + 1 & 1][nt]) f[i & 1][s].push_back (v);
int ed = i + val[i + 1 & 1][nt];
if (a[ed + 1][P[0]] == a[i][P[0]]){
T.push_back (P[0]);
val[i & 1][s] = val[i + 1 & 1][mp[T]] + 1;
}
else val[i & 1][s] = val[i + 1 & 1][nt] + 1;
}
}
int len = 0;
for (Int s = 1;s <= cnt;++ s) chkmax (len,val[i & 1][s]);
ans += len;
}
write (ans),putchar ('\n');
return 0;
}