题意
给两个字符串,求长度最短的字符串的长度以及个数,使得给出的两个串都是这个串的子串。
分析
LCS的变形,首先长度自然是len(s1)+len(s2)-len(LCS)。关键是有多少个这样的字符串。现在知道有两种DP的方法。
题意
给两个字符串,求长度最短的字符串的长度以及个数,使得给出的两个串都是这个串的子串。
分析
LCS的变形,首先长度自然是len(s1)+len(s2)-len(LCS)。关键是有多少个这样的字符串。现在知道有两种DP的方法。
方法一(三维DP)
设状态:
那么转移方程:
考虑当前这个状态是由上一个状态加一个字母而来,那么转移时考虑这个字母是不是LCS中的字母
注意初始化要把所有dp[i][i][0]和dp[i][0][i]初始化为0
(也可以递推来写,不过初始化不一样,见下面代码)
方法二(二维DP)
看到这种方法在求LCS的时候就把个数求了出来,暂时没弄懂,思考过后再来补充一波
设状态:
转移方程:
LCS按常规方法求
AC代码
姿势1
//LightOJ 1013 Love Calculator
//AC 2016-8-9 16:12:26
//DP
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <list>
#include <sstream>
#include <stack>
using namespace std;
#define cls(x) memset(x,0,sizeof x)
#define inf(x) memset(x,0x3f,sizeof x)
#define neg(x) memset(x,-1,sizeof x)
#define ninf(x) memset(x,0xc0,sizeof x)
#define st0(x) memset(x,false,sizeof x)
#define st1(x) memset(x,true,sizeof x)
#define INF 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define input(x) scanf("%d",&(x))
#define bug cout<<"here"<<endl;
//#define debug
int T;
char s1[100],s2[100];
long long dp[100][100][100];
int main()
{
#ifdef debug
freopen("E:\Documents\code\input.txt","r",stdin);
freopen("E:\Documents\code\output.txt","w",stdout);
#endif
input(T);
for(int kase=1;kase<=T;++kase)
{
scanf("%s %s",s1+1,s2+1);
int len1=strlen(s1+1),len2=strlen(s2+1);
cls(dp);
for(int i=0;i<=max(len1,len2);++i)
dp[i][i][0]=dp[i][0][i]=1;
for(int i=1;i<=len1+len2;++i)
{
for(int j=1;j<=len1;++j)
{
for(int k=1;k<=len2;++k)
{
if(s1[j]==s2[k]) dp[i][j][k]=dp[i-1][j-1][k-1];
else dp[i][j][k]=dp[i-1][j][k-1]+dp[i-1][j-1][k];
}
}
}
int res=max(len1,len2);
for(;res<=len1+len2;++res)
if(dp[res][len1][len2]) break;
printf("Case %d: %d %lld
",kase,res,dp[res][len1][len2]);
}
return 0;
}
姿势2
//LightOJ 1013 Love Calculator
//AC 2016-8-9 16:25:35
//DP
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <list>
#include <sstream>
#include <stack>
using namespace std;
#define cls(x) memset(x,0,sizeof x)
#define inf(x) memset(x,0x3f,sizeof x)
#define neg(x) memset(x,-1,sizeof x)
#define ninf(x) memset(x,0xc0,sizeof x)
#define st0(x) memset(x,false,sizeof x)
#define st1(x) memset(x,true,sizeof x)
#define INF 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define input(x) scanf("%d",&(x))
#define bug cout<<"here"<<endl;
//#define debug
int T;
char s1[50],s2[50];
int dp[50][50];
long long cnt[100][50][50];
int main()
{
#ifdef debug
freopen("E:\Documents\code\input.txt","r",stdin);
freopen("E:\Documents\code\output.txt","w",stdout);
#endif
input(T);
for(int kase=1;kase<=T;++kase)
{
scanf("%s",s1+1);scanf("%s",s2+1);
int len1=strlen(s1+1),len2=strlen(s2+1);
cls(dp);
for(int i=1;i<=len1;++i)
{
for(int j=1;j<=len2;++j)
{
if(s1[i]==s2[j])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
cls(cnt);
int len=len1+len2-dp[len1][len2];
cnt[0][0][0]=1;
for(int i=0;i<=len;++i)
{
for(int j=0;j<=len1;++j)
{
for(int k=0;k<=len2;++k)
{
if(s1[j+1]==s2[k+1])
cnt[i+1][j+1][k+1]+=cnt[i][j][k];
else
{
cnt[i+1][j+1][k]+=cnt[i][j][k];
cnt[i+1][j][k+1]+=cnt[i][j][k];
}
}
}
}
printf("Case %d: %d %lld
",kase,len,cnt[len][len1][len2]);
}
return 0;
}
姿势3
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <list>
#include <sstream>
#include <stack>
using namespace std;
#define cls(x) memset(x,0,sizeof x)
#define inf(x) memset(x,0x3f,sizeof x)
#define neg(x) memset(x,-1,sizeof x)
#define ninf(x) memset(x,0xc0,sizeof x)
#define st0(x) memset(x,false,sizeof x)
#define st1(x) memset(x,true,sizeof x)
#define INF 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define input(x) scanf("%d",&(x))
#define bug cout<<"here"<<endl;
//#define debug
int T;
char s1[40],s2[40];
int dp[40][40];
long long cnt[40][40];
long long fact[40];
int main()
{
#ifdef debug
freopen("E:\Documents\code\input.txt","r",stdin);
freopen("E:\Documents\code\output.txt","w",stdout);
#endif
input(T);
for(int kase=1;kase<=T;++kase)
{
scanf("%s %s",s1+1,s2+1);
cls(dp);cls(cnt);
int len1=strlen(s1+1),len2=strlen(s2+1);
for(int i=0;i<=len1;++i)
cnt[i][0]=1;
for(int i=0;i<=len2;++i)
cnt[0][i]=1;
for(int i=1;i<=len1;++i)
{
for(int j=1;j<=len2;++j)
{
if(s1[i]==s2[j])
{
dp[i][j]=dp[i-1][j-1]+1;
cnt[i][j]+=cnt[i-1][j-1];
}
else
{
if(dp[i-1][j]>dp[i][j-1])
{
dp[i][j]=dp[i-1][j];
cnt[i][j]=cnt[i-1][j];
}
else if(dp[i-1][j]<dp[i][j-1])
{
dp[i][j]=dp[i][j-1];
cnt[i][j]=cnt[i][j-1];
}
else
{
dp[i][j]=dp[i][j-1];
cnt[i][j]=cnt[i][j-1]+cnt[i-1][j];
}
}
}
}
for(int i=0;i<=len1;++i)
{
for(int j=0;j<=len2;++j)
cout<<cnt[i][j]<<" ";
cout<<endl;
}
printf("Case %d: %d ",kase,len1+len2-dp[len1][len2]);
cout<<cnt[len1][len2]<<endl;
}
return 0;
}