P10047 CCPC 2023 北京市赛 勿蹖宠物 Sol
可恶的DP,竟然变成串串的模样来拷打我。(虽然好像是有用串串的写法的)。
如果只是从一边加,问题会非常坐牢,根本没法DP。因此我们考虑从两边加。
发现串长总和很小,也就是说,假设我们设置 \(f[i][j]\),其中 \(i,j\) 记录的都是当前在哪个串的哪个位置,那么复杂度我们是能够接受的。
因此,我们不妨设置 \(f[i][j]\),表示在匹配了 \(p\) 对位置,目前在匹配第 \(p+1\) 对,上一对中左边的状态为 \(i\),右边的状态为 \(j\)。但是这样子我们容易发现在统计答案时变得坐牢了。因此我们将右边的状态错位成目前要匹配的状态为 \(j\),这样子在统计答案时,就会形如 \([0,k]\) 与 \([k+1,l-1]\),而不是 \([k,l-1]\)。这是一个很有小巧思的设计。
Code
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const int mod = 1000000007;
const int N = 1000;
int f[N][N];
int g[N][N];
int id[N][N];
pair<int,int> idn[N];
string s[N];
int n,l,cnt;
pair<int,int> vec_l[N],vec_r[N];
int main(){
IOS;
cin >> n >> l;
for(int i=1;i<=n;i++){
cin >> s[i];
int len = s[i].size();
for(int j=0;j<len-1;j++){
idn[++cnt] = {i,j};
id[i][j] = cnt;
}
}
f[0][0] = 1;
for(int P=0;P<l/2;P++){
memset(g,0,sizeof g);
for(int i=0;i<=cnt;i++){
for(int j=0;j<=cnt;j++){
if(!f[i][j]) continue;
int sizl,sizr;
sizl = sizr = 0;
if(i)
vec_l[sizl++] = {idn[i].fi,idn[i].se+1};
else
for(int _=1;_<=n;_++)
vec_l[sizl++] = {_,0};
if(j)
vec_r[sizr++] = {idn[j].fi,idn[j].se};
else
for(int _=1;_<=n;_++)
vec_r[sizr++] = {_,s[_].size()-1};
for(int i$$=0;i$$<sizl;i$$++){
for(int j$$=0;j$$<sizr;j$$++){
pair<int,int> x = vec_l[i$$];
pair<int,int> y = vec_r[j$$];
if(s[x.fi][x.se] != s[y.fi][y.se]) continue;
int tox,toy;
tox = id[x.fi][x.se];
if(y.se == 0) toy = 0;
else toy = id[y.fi][y.se-1];
(g[tox][toy] += f[i][j]) %= mod;
}
}
}
}
for(int i=0;i<=cnt;i++)
for(int j=0;j<=cnt;j++)
f[i][j] = g[i][j];
}
LL ans = 0;
if(l % 2 == 0){
for(int i=0;i<=cnt;i++)
(ans += f[i][i]) %= mod;
}
else{
for(int i=1;i<=n;i++){
if(s[i].size() == 1){
(ans += f[0][0]) %= mod;
continue;
}
(ans += f[0][id[i][0]]) %= mod;
(ans += f[id[i][s[i].size()-2]][0]) %= mod;
for(int j=1;j<s[i].size()-1;j++)
(ans += f[id[i][j-1]][id[i][j]]) %= mod;
}
}
cout << ans << "\n";
return 0;
}

浙公网安备 33010602011771号