LightOJ 1013 LCS+记忆化搜索

http://www.lightoj.com/volume_showproblem.php?problem=1013

题目大意:

给两个字符串,问最短的满足子串包含给的两个字符串的字符串的最短长度,以及最短长度的字符串的个数。

第一个问题就是简单的LCS,两个串长度和减去公共部分。

第二个问题要进行记忆话搜索来查找。dp(i,j,l)(第一个串i位,第二个串j位,总串l位)

转移方程

dp(i,j,l) = dp(i-1,j-1,l-1) (s1[i] = s2[j]时)

dp(i,j,l) = dp(i-1,j,l-1) + dp(i, j-1, l-1) (s1[i] != s2[j]时)

#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <string>
#include <math.h>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-9;
const int N = 30 + 5;
int t,n,m,len,kase = 0;
int dp1[N][N];
LL dp2[N][N][2*N];
char s1[N],s2[N];
int lcs()
{
    memset(dp1, 0, sizeof(dp1));
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            if(s1[i] == s2[j])
                dp1[i][j] = dp1[i-1][j-1] + 1;
            else
                dp1[i][j] = max(dp1[i-1][j], dp1[i][j-1]);
        }
    }
    return dp1[n][m];
}

LL dfs(int i, int j, int l)
{
    LL &ans = dp2[i][j][l];
    if(ans != -1) return ans;
    else if(l == 0) return i == 0 && j == 0;
    else if(i == 0) return ans = dfs(i, j-1, l-1);
    else if(j == 0) return ans = dfs(i-1, j, l-1);
    else if(s1[i] == s2[j]) return ans = dfs(i-1, j-1, l-1);
    else return ans = dfs(i-1, j, l-1) + dfs(i, j-1, l-1);
}

int main()
{
    scanf("%d", &t);
    while(t--)
    {
        scanf("%s%s", s1+1, s2+1);
        n = strlen(s1+1);
        m = strlen(s2+1);
        len = n + m - lcs();
        memset(dp2, -1, sizeof(dp2));
        printf("Case %d: %d %lld\n", ++kase, len, dfs(n,m,len));
    }
    return 0;
}
时间: 2024-10-23 08:35:34

LightOJ 1013 LCS+记忆化搜索的相关文章

Easy Game LightOJ - 1031(记忆化搜索+博弈)

You are playing a two player game. Initially there are n integer numbers in an array and player A and B get chance to take them alternatively. Each player can take one or more numbers from the left or right end of the array but cannot take from both

HDU 1513 Palindrome:LCS(最长公共子序列)or 记忆化搜索

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1513 题意: 给你一个字符串s,你可以在s中的任意位置添加任意字符,问你将s变成一个回文串最少需要添加字符的个数. 题解1(LCS): 很神奇的做法. 先求s和s的反串的LCS,也就是原串中已经满足回文性质的字符个数. 然后要变成回文串的话,只需要为剩下的每个落单的字符,相应地插入一个和它相同的字符即可. 所以答案是:s.size()-LCS(s,rev(s)) 另外,求LCS时只会用到lcs[i-

uva 1076 - Password Suspects(AC自动机+记忆化搜索)

题目链接:uva 1076 - Password Suspects 题目大意:有一个长度为n的密码,存在m个子串,问说有多少种字符串满足,如果满足个数不大于42,按照字典序输出. 解题思路:根据子串构建AC自动机,然后记忆化搜索,dp[i][u][s]表示第i个字符,在u节点,匹配s个子串. #include <cstdio> #include <cstring> #include <queue> #include <string> #include <

poj 1579(动态规划初探之记忆化搜索)

Function Run Fun Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17843   Accepted: 9112 Description We all love recursion! Don't we? Consider a three-parameter recursive function w(a, b, c): if a <= 0 or b <= 0 or c <= 0, then w(a, b

记忆化搜索,FatMouse and Cheese

1.从gird[0][0]出发,每次的方向搜索一下,每次步数搜索一下 for(i=0; i<4; i++) { for(j=1; j<=k; j++) { int tx=x+d[i][0]*j; int ty=y+d[i][1]*j; if(tx>=0&&tx<n&&ty>=0&&ty<n&&grid[x][y]<grid[tx][ty]) { int temp=memSearch(tx,ty); i

LightOJ1417 Forwarding Emails(强连通分量+缩点+记忆化搜索)

题目大概是,每个人收到信息后会把信息发给他认识的一个人如此下去,问一开始要把信息发送给谁这样看到信息的人数最多. 首先找出图中的SCC并记录每个SCC里面的点数,如果传到一个SCC,那么里面的人都可以看到信息. 然后SCC缩点后就形成DAG,直接记忆化搜索,d(u)搜索从u点出发开始传最多能传多少人. 最后就是找答案了. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namesp

POJ1088(记忆化搜索)

经典记忆化搜索题目.当 从每个点一次进行搜索时要采用 记忆化搜索 #include"cstdio" #include"algorithm" using namespace std; const int MAXN=105; int g[MAXN][MAXN]; int t[MAXN][MAXN]; int maxn; int n,m; int by,bx; int ans; int dx[4]={1,0,-1,0}; int dy[4]={0,1,0,-1}; int

BZOJ 1079: [SCOI2008]着色方案 记忆化搜索

1079: [SCOI2008]着色方案 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1079 Description 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块.所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相邻木块颜色不同的

Codeforces Div.301D Bad Luck Island(概率dp+记忆化搜索)

一道概率dp问题. 题目链接:http://codeforces.com/contest/540/problem/D 题目大意:一个岛上有r个石头,s个剪子,p个布,他们之间随机挑出两个相遇,如果不是相同物种,就会有一个消失,分别求出最后这座岛上只剩下一个物种的概率. 我们用dp[i][j][k]来存储i个石头,j个剪刀,k个布时,某物种的存活概率,共dp三次,算出三个物种分别的概率. 首先,我们需要把对应想求的物种概率初始化,这里以石头为例,那么对于i从1到r,不难理解dp[i][0][0]=