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;
}
posted @ 2026-05-20 12:48  WinterXorSnow  阅读(8)  评论(0)    收藏  举报