題意
給兩個字符串,求長度最短的字符串的長度以及個數,使得給出的兩個串都是這個串的子串。
分析
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\n",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\n",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;
}