• CF49E Common ancestor


    CF49E Common ancestor

    CF

    题意

    有两个字符串S和T,并提供一些转换方案(每一个方案可以将一个字母转换成两个字母),求S和T是否可以由一个相同的字符串转换出来,如果可以,求最短的字符串,若不行,输出-1。

    思路

    先不去考虑S和T,先考虑单独去某个字符串是否能够由某一个字母扩展而成。

    image

    而在实际扩展的过程中是不断使用转换方案的。

    image

    若原字母能够扩展出一段区间,那么必然存在一种方案,使得原字母先扩展得到两个新字母,并有这两个字母接管两个子区间。

    image

    对于字符串S和字符串T来说,如果说中间存在由一个相同的字母可以扩展出一段距离的话,那么就不妨尝试将这个字母加入到初始字符串。

    image

    定义一个dp[i][j]代表着说对于S串前i个元素来说和对于T串前j个元素来说最短的初始字符串。

    #include <bits/stdc++.h>
    #define N 60
    
    using namespace std;
    int rec[N][4];
    bool ok[2][N][N][30];
    int dp[N][N];
    
    void solve() {
    	char s[N], t[N], op[5];
    	int n;
    	cin >> s + 1 >> t + 1;
    	int lens = strlen(s + 1);
    	int lent = strlen(t + 1);
    
    	cin >> n;
    	for (int i = 0; i < n; i++) {
    		cin >> op;
    
    		rec[i][0] = op[0] - 'a';
    		rec[i][1] = op[3] - 'a';
    		rec[i][2] = op[4] - 'a';
    	}
    	for (int i = 1; i <= lens; i++)
    		ok[0][i][i][ s[i] - 'a' ] = 1;
    
    	for (int i = 1; i <= lent; i++)
    		ok[1][i][i][ t[i] - 'a' ] = 1;
    
    	for (int i = 2; i <= lens; i++)
    		for (int st = 1; st <= lens - i + 1; st++) {
    			int ed = st + i - 1;
    			for (int k = st + 1; k <= ed; k++)
    				for (int c = 0; c < n; c++) {
    
    					ok[0][st][ed][ rec[c][0] ] |= (ok[0][st][k - 1][ rec[c][1] ] && ok[0][k][ed][ rec[c][2]]);
    				}
    		}
    
    	for (int i = 2; i <= lent; i++)
    		for (int st = 1; st <= lent - i + 1; st++) {
    			int ed = st + i - 1;
    			for (int k = st + 1; k <= ed; k++)
    				for (int c = 0; c < n; c++) {
    
    					ok[1][st][ed][ rec[c][0] ] |= (ok[1][st][k - 1][ rec[c][1] ] && ok[1][k][ed][ rec[c][2]]);
    				}
    		}
    
    	memset(dp, 0x3f, sizeof(dp));
    	dp[0][0] = 0;
    	for (int i = 1; i <= lens; i++)
    		for (int j = 1; j <= lent; j++)
    			for (int k = 1; k <= i; k++)
    				for (int l = 1; l <= j; l++)
    					for (int c = 0; c < 26; c++)
    						if (ok[0][k][i][c] && ok[1][l][j][c])
    							dp[i][j] = min(dp[i][j], dp[k - 1][l - 1] + 1);
    
    	if (dp[lens][lent] > 100)
    		cout << -1;
    	else
    		cout << dp[lens][lent];
    }
    
    int main() {
    	int T_ = 1;
    	while (T_--)
    		solve();
    	return 0;
    }
    
  • 相关阅读:
    Bash的提示符
    小笨霖英语笔记本(5)
    什么是VLAN
    阅读笔记:双核心Opteron处理器
    小笨霖英语笔记本(4)
    搭乘CCNUMA快车
    得到tnsnames.ora文件的位置 zz
    关于64位Windows操作系统中的注册表 zz
    Temp.Misc
    HttpHandler HttpModule入门篇
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/16171987.html
Copyright © 2020-2023  润新知