F. Rotating Substrings(dp)

F. Rotating Substrings(dp)

思路:dpdpdp,找到最大匹配数然后用nnn去减,因为每个字母最多动一次就行了。

dp[i][j]dp[i][j]dp[i][j]为SSS串中前iii个字符和TTT串中前jjj个字符的最大匹配。

转移状态时注意因为每次操作字符往左移动,所以必须满足iji\leq ji≤j,不然永远匹配不了。

转移方程:

{dp[i+1][j]=max(dp[i+1][j],dp[i][j]),(i<n)dp[i][j+1]=max(dp[i][j+1],dp[i][j]),(j<n)\begin{cases}dp[i+1][j]=max(dp[i+1][j],dp[i][j]),(i<n)\\dp[i][j+1]=max(dp[i][j+1],dp[i][j]),(j<n)\end{cases}{dp[i+1][j]=max(dp[i+1][j],dp[i][j]),(i<n)dp[i][j+1]=max(dp[i][j+1],dp[i][j]),(j<n)​

{dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j])(S[i]==T[j]SiT)\begin{cases}dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j])\\(S[i]==T[j]且满足S中前i个所有对应字母数小于等于T中字母数)\end{cases}{dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j])(S[i]==T[j]且满足S中前i个所有对应字母数小于等于T中字母数)​

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
#define mst(a) memset(a,0,sizeof a)
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
void solve(){
	int n;
	string s,t;
	cin>>n>>s>>t;
	vector<vector<int> >numS(n+1,vector<int>(26)),numT(n+1,vector<int>(26));
	for(int i=0;i<n;i++){
		numS[i+1]=numS[i];//直接整个赋值 
		numT[i+1]=numT[i];
	 	numS[i+1][s[i]-'a']++;
	 	numT[i+1][t[i]-'a']++;
	}
		/*for(int i=0;i<26;i++)
		printf("%d %d\n",numS[1][i],numT[1][i]);
		*/
	if(numS[n]!=numT[n]){
		cout<<-1<<endl;
		return ;
	}
	vector<vector<int> >dp(n+1,vector<int>(n+1,-1e9));
	dp[0][0]=0;
		for(int i=0;i<=n;i++)
			for(int j=0;j<=n;j++){
				 if(i<n) dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
				 if(j<n) dp[i][j+1]=max(dp[i][j+1],dp[i][j]);
				 if(i<=j&&i<n&&j<n&&s[i]==t[j]){
				 	 int f=0;
				 	 for(int k=0;k<26;k++)
				 	 	 if(numS[i][k]>numT[j][k]) f=1;
				 	 if(!f) dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j]+1);
				 }
			}
		cout<<n-dp[n][n]<<endl;//n-最大匹配 
}
int main(){
	IOS;
	int T;
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
} 
上一篇:Problem 550A - Two Substrings


下一篇:Python打印乘法口诀表