zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
    
    
    
    
    
    
    
  • 相关阅读:
    298. Binary Tree Longest Consecutive Sequence
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    163. Missing Ranges
    336. Palindrome Pairs
    727. Minimum Window Subsequence
    211. Add and Search Word
    年底购物狂欢,移动支付安全不容忽视
    成为程序员前需要做的10件事
    全球首推iOS应用防破解技术!
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13037647.html
Copyright © 2011-2022 走看看