Two
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 670 Accepted Submission(s): 308
For each test case, the first line cantains two integers N,M(1≤N,M≤1000) . The next line contains N integers. The next line followed M integers. All integers are between 1 and 1000.
3 2 1 2 3 2 1 3 2 1 2 3 1 2
2 3
思路:因为刚做了cf的一道关于lcs的题(也就是下面的一道题),思路和其类似。由于数字范围是0~1000,所以我们可以记录0~1000在B串的每个位置,由于数字可以重复,枚举A串中每个位置的数字及该数字在B串的相应的每个位置,求到当前位置且包含该位置的公共子序列集合的个数。然后把所有情况加起来就是answer。因为拿树状数组维护前缀和,所以复杂度O(n^2log(n)。可能数据比较随机吧,跑了31ms比n^2的还快。
看了下题解,复杂度比我的优多了,O(n^2)的。表示A中前i个数与B中前j个数构成的公共子序列个数。代码见后面。
Gargari got bored to play with the bishops and now, after solving the problem about them, he is trying to do math homework. In a math book he have foundk permutations. Each of them consists of numbers1, 2, ..., n in some order. Now he should find the length of the longest common subsequence of these permutations. Can you help Gargari?
You can read about longest common subsequence there: https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
The first line contains two integers n andk(1 ≤ n ≤ 1000; 2 ≤ k ≤ 5). Each of the nextk lines contains integers1, 2, ..., n in some order — description of the current permutation.
Print the length of the longest common subsequence.
4 3 1 4 2 3 4 1 2 3 1 2 4 3
3
The answer for the first test sample is subsequence [1, 2, 3].
题意:求k个1~n排列的LCS。
思路:由于每个数字在1个排列中只出现一次,所以我们可以拿vector记录每个数字在k个排列中出现的位置。然后以其中一个序列为标准,枚举这个序列中每个数字,求以其结尾的LCS,其实就是1~i-1位置数字在每个序列中位置比当前数字在相应序列中位置靠前的最大LCS+1.
详细见代码:
hdu O(n^2logn):
//最坏O(n^2logn),最好O(n),31ms
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn = 1e3+10;
const int MOD = 1e9+7;
int A[1010];
int B[1010];
vector<int>v[1010];
int dp[1010];
inline int lowbit(int a)
{
return a&(-a);
}
void update(int a,int b)
{
while(a<maxn)
{
dp[a]+=b;
dp[a]%=MOD;
a+=lowbit(a);
}
}
int query(int a)
{
int ans=0;
while(a)
{
ans=(ans+dp[a])%MOD;
a-=lowbit(a);
}
return ans;
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j;
for(i=1;i<=n;i++)
{
scanf("%d",&A[i]);
}
int ans=0;
for(j=1;j<=m;j++)
{
scanf("%d",&B[j]);
v[B[j]].push_back(j);
}
memset(dp,0,sizeof dp);
for(i=1;i<=n;i++)
{
for(j=v[A[i]].size()-1;j>=0;j--)
{
int tmp=(query(v[A[i]][j]-1)+1)%MOD;
ans=(ans+tmp)%MOD;
update(v[A[i]][j],tmp);
}
}
for(i=0;i<maxn;i++)
v[i].clear();
printf("%d\n",ans);
}
return 0;
}
hdu O(n^2):
//O(n^2) 140ms
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1e3+100;
const int MOD = 1e9+7;
int A[maxn];
int B[maxn];
int dp[maxn][maxn];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(dp,0,sizeof dp);
int i,j;
for(i=1;i<=n;i++)
scanf("%d",&A[i]);
for(i=1;i<=m;i++)
scanf("%d",&B[i]);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
dp[i][j]=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1])%MOD;
if(A[i]==B[j])
dp[i][j]=((dp[i][j]+dp[i-1][j-1])%MOD+1)%MOD;
}
}
printf("%d\n",(dp[n][m]+MOD)%MOD);
}
return 0;
}
cf :
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn = 1e3+100;
int A[7][1010];
int dp[1010];
vector<int>v[1010];
int main()
{
int n,m;
int i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
scanf("%d",&A[i][j]),v[A[i][j]].push_back(j);
}
for(i=1;i<=n;i++)
{
dp[A[1][i]]=max(1,dp[A[1][i]]);
for(k=1;k<=n;k++)
{
if(k==A[1][i]) continue;
int u;
for(u=0;u<m;u++)
{
if(v[k][u]>v[A[1][i]][u]) break;
}
if(u>=m) dp[A[1][i]]=max(dp[A[1][i]],dp[k]+1);
}
}
int ans=1;
for(i=1;i<=n;i++)
ans=max(ans,dp[i]);
cout<<ans<<endl;
return 0;
}