LCS 模板+规定长度的上升子序列个数(数值不同为不同)
第一个是最长公共子序列 不连续
#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
int dp[1010][1010];
int main()
{
char a[1010],b[1010];
while (scanf ("%s%s",a,b)!=EOF)
{
int la=strlen(a);
int lb=strlen(b);
for (int i=0;i<la;i++) dp[i][0]=0;
for (int i=0;i<lb;i++) dp[0][i]=0;
for (int i=0;i<la;i++)
{
for (int j=0;j<lb;j++)
{
if (a[i]==b[j])
dp[i+1][j+1]=dp[i][j]+1;
else dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j]);
}
}
printf ("%d\n",dp[la][lb]);
}
return 0;
}
第二个是最长公共子串,要求连续
找 两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。其实这又是一个序贯决策问题,可以用动态规划来求解。我们采用一个二维矩阵来记录中间的结 果。这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab")
b a b
c 0 0 0
a 0 1 0
b 1 0 1
a 0 1 0
我们看矩阵的斜对角线最长的那个就能找出最长公共子串。
不过在二维矩阵上找最长的由1组成的斜对角线也是件麻烦费时的事,下面改进:当要在矩阵是填1时让它等于其左上角元素加1。
b a b
c 0 0 0
a 0 1 0
b 1 0 2
a 0 2 0
这样矩阵中的最大元素就是 最长公共子串的长度。
在构造这个二维矩阵的过程中由于得出矩阵的某一行后其上一行就没用了,所以实际上在程序中可以用一维数组来代替这个矩阵。
代码如下:
#include<iostream>
#include<cstring>
#include<vector>
using
namespace
std;
//str1为横向,str2这纵向
const
string LCS(
const
string& str1,
const
string& str2)
{
int
xlen=str1.size();
//横向长度
vector<
int
> tmp(xlen);
//保存矩阵的上一行
vector<
int
> arr(tmp);
//当前行
int
ylen=str2.size();
//纵向长度
int
maxele=0;
//矩阵元素中的最大值
int
pos=0;
//矩阵元素最大值出现在第几列
for
(
int
i=0;i<ylen;i++)
{
string s=str2.substr(i,1);
arr.assign(xlen,0);
//数组清0
for
(
int
j=0;j<xlen;j++)
{
if
(str1.compare(j,1,s)==0)
{
if
(j==0)
arr[j]=1;
else
arr[j]=tmp[j-1]+1;
if
(arr[j]>maxele)
{
maxele=arr[j];
pos=j;
}
}
}
tmp.assign(arr.begin(),arr.end());
}
string res=str1.substr(pos-maxele+1,maxele);
return
res;
}
int
main()
{
string str1(
"21232523311324"
);
string str2(
"312123223445"
);
string lcs=LCS(str1,str2);
cout<<lcs<<endl;
return
0;
}
#include<iostream>
#include<cstring>
#define maxn 105
#define mod 1000000007
using namespace std;
int dp[maxn][maxn];
int num[maxn];
int vis[maxn];
int main()
{
int T;
cin>>T;
while (T > 0)
{
T--;
int n, m, x;
cin>>n>>m;
int last = -1;
int tot = 0;
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis)); //标记值是否用过
for (int i=1; i<=n; i++)
{
cin>>num[i];
dp[i][1] = 1;
}
for (int i=2; i<=n; i++)
for (int j=1; j<=n; j++)
{
for (int k=i-1; k>=1; k--)
if (num[i] > num[k] && !vis[num[k]])
{
vis[num[k]] = 1;
dp[i][j] += dp[k][j-1];
dp[i][j] %= mod;
}
memset(vis,0,sizeof(vis));
}
memset(vis,0,sizeof(vis));
int ans = 0;
for (int i=n; i>=1; i--)
{
if (vis[num[i]])
continue;
vis[num[i]] = 1;
ans += dp[i][m];
ans %= mod;
}
cout<<ans<<endl;
}
return 0;
}