最长公共子序列变形

Yes, you are developing a ‘Love calculator‘. The software would be quite complex such that nobody could crack the exact behavior of the software.

So, given two names your software will generate the percentage of their ‘love‘ according to their names. The software requires the following things:

  1. The length of the shortest string that contains the names as subsequence.
  2. Total number of unique shortest strings which contain the names as subsequence.

Now your task is to find these parts.

Input

Input starts with an integer T (≤ 125), denoting the number of test cases.

Each of the test cases consists of two lines each containing a name. The names will contain no more than 30 capital letters.

Output

For each of the test cases, you need to print
one line of output. The output for each test case starts with the test
case number, followed by the shortest length of the string and the
number of unique strings that satisfies the given conditions.

You can assume that the number of unique strings will always be less than 263. Look at the sample output for the exact format.

Sample Input

3

USA

USSR

LAILI

MAJNU

SHAHJAHAN

MOMTAJ

Sample Output

Case 1: 5 3

Case 2: 9 40

Case 3: 13 15

题意 : 两个小问,第一问是求一个最短的长度构成的序列同时包含这两个序列,第二问是求构成这个最短序列的方案数

思路分析 : 第一问就是用两个串的长度减去 lcs

      第二问定义 dp[i][j][k] 表示第一个串用了 i 个字符, 第二个串用了j 个字符,并且当前匹配用去了 k 个字符的方案数

    转移过程类似求 lcs 的过程

代码示例:

#define ll long long

char a[100], b[100];
ll dp[100][100][100];
ll dp2[100][100];
ll lena, lenb, num;

void solve(){

    lena = strlen(a+1);
    lenb = strlen(b+1);
    memset(dp2, 0, sizeof(dp2));
    for(ll i = 1; i <= lena; i++){
        for(ll j = 1; j <= lenb; j++){
            if (a[i] == b[j]) dp2[i][j] = dp2[i-1][j-1]+1;
            else dp2[i][j] = max(dp2[i-1][j], dp2[i][j-1]);
        }
    }
    memset(dp, 0, sizeof(dp));
    dp[0][0][1] = 1;
    num = dp2[lena][lenb];
    for(ll i = 1; i <= lena; i++) dp[i][0][1] = 1;
    for(ll i = 1; i <= lenb; i++) dp[0][i][1] = 1;

    for(ll i = 1; i <= lena; i++){
        for(ll j = 1; j <= lenb; j++){
            for(ll k = 1; k <= num+1; k++){
                if (a[i] == b[j]) dp[i][j][k] = dp[i-1][j-1][k-1];
                else dp[i][j][k] = dp[i-1][j][k]+dp[i][j-1][k];
            }
        }
    }

}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    ll t;
    ll cas = 1;

    cin >> t;
    while(t--){
        scanf("%s%s", a+1, b+1);
        solve();
        printf("Case %lld: %lld %lld\n", cas++, lena+lenb-num, dp[lena][lenb][num+1]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ccut-ry/p/10296013.html

时间: 2024-11-01 18:20:39

最长公共子序列变形的相关文章

poj1159--Palindrome(dp:最长公共子序列变形 + 滚动数组)

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 53414   Accepted: 18449 Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a

UVA 10723--Cyborg Genes+最长公共子序列变形

题目链接:点击进入 首先对于长度最短的情况是很容易确定的,只需要用两个字符串的长度和减去他们的最长公共子序列长度.然后比较麻烦的就是合乎要求的字符串的个数,其实我们也可以用类似于最长公共子序列的dp来求. 设dp[i][j]表示str1的前i个字符和str2的前j个字符所得到的满足要求的字符串,则如果str[i]==str[j],则dp[i][j]+=dp[i-1][j-1]; 否则就要根据i,j这两个位置上的最长公共子序列长度进行讨论,具体见代码. 代码如下: #include<iostrea

hdu1243(最长公共子序列变形)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1243 分析:dp[i][j]表示前i个子弹去炸前j个恐怖分子得到的最大分.其实就是最长公共子序列加每个字母值为1,这里每个字母代表的值变化了一下. 状态转移方程:if(s1[i-1]==s2[j-1])dp[nxt][j]=dp[cur][j-1]+val[s1[i-1]];                              else  dp[nxt][j]=max(dp[nxt][j-1]

51Nod 1092 回文字符串 | 最长公共子序列变形

求字符串和其逆的最长公共子序列,需要添加的字符数就为长度-最长公共子序列长 #include "stdio.h" #include "string.h" #define maxn 1005 char s[maxn],s1[maxn]; int dp[maxn][maxn]; int main() { int n=0,i,j,len; scanf("%s",s); len=strlen(s); strcpy(s1,s); strrev(s1); f

POJ 2250(最长公共子序列 变形)

Description In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfilled, and this is not a trivial task for the countries (maybe except for Luxembourg). To enforce that Germa

Human Gene Functions POJ 1080 最长公共子序列变形

Description It is well known that a human gene can be considered as a sequence, consisting of four nucleotides, which are simply denoted by four letters, A, C, G, and T. Biologists have been interested in identifying human genes and determining their

hdu5282 最长公共子序列的变形

http://acm.hdu.edu.cn/showproblem.php?pid=5282 Problem Description Xuejiejie loves strings most. In order to win the favor of her, a young man has two strings X, Y to Xuejiejie. Xuejiejie has never seen such beautiful strings! These days, she is very

最长公共子序列(LCS)

最长公共子序列,英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列.而最长公共子串(要求连续)和最长公共子序列是不同的.       最长公共子序列是一个十分实用的问题,它可以描述两段文字之间的"相似度",即它们的雷同程度,从而能够用来辨别抄袭.对一段文字进行修改之后,计算改动前后文字的最长公共子序列,将除此子序列外的部分提取出来,

最长公共子序列的代码实现

关于最长公共子序列(LCS)的相关知识,http://blog.csdn.net/liufeng_king/article/details/8500084 这篇文章讲的比较好,在此暂时不再详说. 以下是我代码实现两种方式:递归+递推: 1 #include <bits/stdc++.h> 2 using namespace std; 3 int A[100]; 4 int B[100]; 5 6 //int B[]={2,3,5,6,9,8,4}; 7 int d[100][100]={0};