• CodeForces 1363F. Rotating Substrings


    题意:你被给予了两个字符串s和t,每个字符串的长度都是n并且是小写字母,你的目标是让s变成t。
    你可以进行如下的操作多次,使得字符串s变成字符串t,选择字符串s的子串并使得它旋转,即让(s[l, l + 1...r])变成字符串(s[r, l, l + 1...r - 1]),其它字符保持原有的位置。求最少的操作次数让字符串s变成字符串t,并确定是否它可以。

    分析:每一个操作可以让一个字符提到前面的任何位置,并不能提到到后面,最少的操作次数是n - 两个字符串的最长公共子序列,但是这个最长公共子序列是受到限制的,受到什么限制呢?就是两个字符串匹配的时候,比如s的字符i和t的字符j匹配的时候,那么s的字符i后面的每种类型的字符数量都要大于t的j字符后面的每种类型的字符数量,这样s后面不匹配的字符可以提到前面来,我们求最长公共上升子序列的时候,我们的dp方程(dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1))不仅要满足s[i] == t[j],并且满足每种字符的后缀和suf_s[i][alpha]都大于等于suf_t[i][alpha]。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    const int inf = 0x3f3f3f3f;
    
    int main()
    {
    	int t;
    	scanf("%d", &t);
    
    	while (t--)
    	{
    		int n;
    		scanf("%d", &n);
    
    		string s, t;
    		cin >> s >> t;
    
    		string tmps = s, tmpt = t;
    		sort(tmps.begin(), tmps.end()), sort(tmpt.begin(), tmpt.end());
    
    		if (tmps != tmpt)
    		{
    			puts("-1");
    			continue;
    		}
    
    		//偏移一个位置
    		s = "?" + s;
    		t = "?" + t;
    
    		//dp数组
    		vector<vector<int>> dp(n + 1, vector<int>(n + 1));
    		//统计后缀中每个字符的数量
    		vector<vector<int>> suf_s(n + 2, vector<int>(26)), suf_t(n + 2, vector<int>(26));
    
    		for (int i = n; i >= 1; --i)
    		{
    			for (int j = 0; j < 26; ++j)
    			{
    				suf_s[i][j] = suf_s[i + 1][j];
    				suf_t[i][j] = suf_t[i + 1][j];
    			}
    			++suf_s[i][s[i] - 'a'];
    			++suf_t[i][t[i] - 'a'];
    		}
    
    		//求满足限制的最长公共子序列
    		//初始化
    		dp[0][0] = 0;
    		for(int i = 1; i <= n; ++i)
    			for (int j = 1; j <= n; ++j)
    			{
    				dp[i][j] = max(dp[i][j], max(dp[i - 1][j], dp[i][j - 1]));
    				if (s[i] == t[j])
    				{
    					//必须满足限制,才能转移
    					bool flag = true;
    					for (int k = 0; k < 26; ++k)
    					{
    						if (suf_s[i][k] < suf_t[j][k])
    							flag = false;
    					}
    					if (flag)
    						dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
    				}
    			}
    		printf("%d
    ", n - dp[n][n]);
    	}
    
    	
    	return 0;
    }
    
    
    
    
    
    
    
    
    
  • 相关阅读:
    C# 上传图片前判断上传图片的宽和高
    PHP调用WebService
    js判断输入字符串长度(汉字算两个字符,字母数字算一个)
    js 验证电话号 座机及手机号
    C# 微信扫码支付 回调页面
    复制文件夹及文件
    html失去获得焦点
    SQL 大数据查询如何进行优化?
    sql表内存占用情况,并进行缩放
    查询被锁的表
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13037647.html
Copyright © 2020-2023  润新知