Longest Common Subsequence
Accepted : Submit :
Time Limit : MS Memory Limit : KB Longest Common Subsequence Bobo has a sequence A=(a1,a2,…,an) of length n. He would like to know f(),f(),f() and f() where f(k) denotes the number of integer sequences X=(x1,x2,x3) where: ≤x1,x2,x3≤m;
The length of longest common subsequence of A and X is exactly k. Note: u is a subsequence of v if and only if u can be obtained by removing some of the entries from v (possibly none).
u is common subsequence of v and w if and only if u is subsequence of v and w. Input The input contains zero or more test cases and is terminated by end-of-file. For each case, The first line contains two integers n,m. The second line contains n integers a1,a2,…,an. ≤n≤
≤m,a1,a2,…,an≤
The number of tests cases does not exceed . Output For each case, output four integers which denote f(),f(),f(),f().
Sample Input Sample Output Note For the second sample, X=(,,) is the only sequence that the length of longest common subsequence of A and X is . Thus, f()=. Source
XTU OnlineJudge /**
题目:Longest Common Subsequence
链接:http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1265
题意:给定序列A,含n个数。和一个数m;
有一个X序列{x1,x2,x3},x1,x2,x3来自[1,m]区间内的数。 设:f(k)表示两个序列的最长公共子序列为k; 求序列X和A满足f(0),f(1),f(2),f(3)的X各有多少种。 思路:f(0)易求。计算出n个数中在m范围内的不同数的数量为cnt,然后计算(m-cnt)^3即可。 对n个数中<=m的数,离散化。 要求f(1),f(2),f(3);
f(3)的X序列内的数一定是n个数中获得。
f(2)的X序列内的数有两种来源,一种是三个数从n个数中获得,然后Longest Common Subsequence为2;
另一种是其中两个是n个数中获得,然后Longest Common Subsequence为2,另外一个是<=m的不包含n个数的数中获得。
f(1)的X序列内的数有三种来源,一种是3个数从n个数中获得,然后Longest Common Subsequence为1;
另一种是两个数从n个数中获得,然后Longest Common Subsequence为1;另外一个是是<=m的不包含n个数的数中获得。
另一种是其中一个是n个数中获得,然后Longest Common Subsequence为1,另外二个是<=m的不包含n个数的数中获得。 设:cnt表示n个数中<=m的数。kind表示n个数中<=m的不同数的种类。m-kind表示不包含n个数的数的种数。 枚举x1,x2,x3全是n个数组成的X序列,所有xi都枚举所有的n个数。 这些序列包含f(3),f(2)第一种来源,f(1)第一种来源的情况数。计算方法:一种是常规的Longest Common Subsequence 的dp求法,但是总时间复杂度为O(N^4);
更好的做法是:预处理next[i][j]表示i这个位置右边第一次出现j这个数的位置。那么可以O(1)判断X序列的Longest Common Subsequence为k。把它们更新到f(k)中。
flag[a[i]][a[j]][a[k]]表示这个序列可以匹配的最大LCS;取最值,最后遍历计算即可。 剩下要求f(2)的第二种来源,f(1)的第二种来源和第三种来源。
f(2)第二种来源:三种可能(x1,x2),(x2,x3),(x1,x3)位置,Longest Common Subsequence为2,另一个位置为m-kind中取。 其实情况数是一样的。f(2) += 3*Q(cnt)*(m-kind);
Q(cnt)表示cnt个数中找到与A序列的Longest Common Subsequence为2的序列数量。暴力枚举两个位置,同上面说的方法。 f(1)第二种来源:三种可能(x1,x2),(x2,x3),(x1,x3)位置,但是Longest Common Subsequence为1;另外一个位置从m-kind中取。 f(1) += 3*P(cnt)*(m-kind);
f(1)第三种来源:三种可能x1,x2,x3位置相同,另外两个位置为m-kind中取。f(1) += 3*kind*(m-kind)*(m-kind); 思考:为什么要用next[i][j]表示i这个位置右边第一次出现j这个数的位置。而不是直接next[i][j]表示j这个数是否在i的右边。
假设: 2 2
那么枚举出来2 2 2. 如果用后者所述定义,那么答案就是3了。实际上只能是2.
*/ #include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> P;
const int maxn = 1e5+;
int flag[][][];
int sign[][];
int mark[];
int n, m;
int cnt , kind;
LL f[];
int a[], z;
int Next[][];
set<int> se;
void NextInit()
{
for(int i = ; i < z; i++){
for(int j = i+; j < z; j++){
if(Next[i][a[j]]==-){
Next[i][a[j]] = j;
}
}
}
}
void lisan()
{
int cnt = ;
set<int>::iterator it;
for(it = se.begin(); it!=se.end(); it++){
mark[*it] = cnt;
cnt++;
}
for(int i = ; i < z; i++){
a[i] = mark[a[i]];
}
}
void init()
{
memset(f, , sizeof f);
memset(Next, -, sizeof Next);
memset(flag, , sizeof flag);
memset(sign, , sizeof sign);
se.clear();
}
int cal(int i,int j,int k)
{
if(Next[i][a[j]]==j&&Next[j][a[k]]==k) return ;
if(Next[i][a[j]]==j) return ;
if(Next[j][a[k]]==k) return ;
if(Next[i][a[k]]==k) return ;
return ;
}
void solve()
{
kind = se.size();
cnt = z;
LL temp = m-kind;
f[] = 1LL*temp*temp*temp;
///枚举三层循环所有序列。
for(int i = ; i < z; i++){
for(int j = ; j < z; j++){
for(int k = ; k < z; k++){
int len = cal(i,j,k);
flag[a[i]][a[j]][a[k]] = max(flag[a[i]][a[j]][a[k]],len);
}
}
} se.clear();///清空原先没有离散的数据。
for(int i = ; i < z; i++){
se.insert(a[i]);
}
set<int>::iterator it, it1, it2;
for(it = se.begin(); it!=se.end(); it++){
for(it1 = se.begin(); it1!=se.end(); it1++){
for(it2 = se.begin(); it2!=se.end(); it2++){
f[flag[*it][*it1][*it2]]++;
}
} } ///枚举两层循环.
int cnt2, cnt1;
for(int i = ; i < z; i++){
for(int j = ; j < z; j++){
int len;
if(Next[i][a[j]]==j) len = ;
else len = ;
sign[a[i]][a[j]]= max(sign[a[i]][a[j]],len);
}
}
cnt1 = cnt2 = ;
for(it = se.begin(); it!=se.end(); it++){
for(it1 = se.begin(); it1!=se.end(); it1++){
if(sign[*it][*it1]==){
cnt2++;
}else cnt1++;
}
} f[] += 1LL**cnt2*(m-kind);
f[] += 1LL**cnt1*(m-kind);
///f(1)第三种来源;
f[] += 1LL**kind*(m-kind)*(m-kind);
}
int main()
{
while(scanf("%d%d",&n,&m)==)
{
z = ;
for(int i = ; i < n; i++) {
scanf("%d",&a[z]);
if(a[z]<=m) z++;
}
init();
for(int i = ; i < z; i++){
se.insert(a[i]);
}
lisan();
NextInit();
solve();
printf("%I64d %I64d %I64d %I64d\n",f[], f[], f[], f[]);
}
return ;
}

2017-5-14 湘潭市赛 Longest Common Subsequence 想法题的更多相关文章

  1. Lintcode:Longest Common Subsequence 解题报告

    Longest Common Subsequence 原题链接:http://lintcode.com/zh-cn/problem/longest-common-subsequence/ Given ...

  2. UVA 10405 Longest Common Subsequence (dp + LCS)

    Problem C: Longest Common Subsequence Sequence 1: Sequence 2: Given two sequences of characters, pri ...

  3. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  4. LintCode Longest Common Subsequence

    原题链接在这里:http://www.lintcode.com/en/problem/longest-common-subsequence/ 题目: Given two strings, find t ...

  5. [UCSD白板题] Longest Common Subsequence of Three Sequences

    Problem Introduction In this problem, your goal is to compute the length of a longest common subsequ ...

  6. LCS(Longest Common Subsequence 最长公共子序列)

    最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

  7. Longest Common Subsequence

    Given two strings, find the longest common subsequence (LCS). Your code should return the length of  ...

  8. Longest Common Subsequence & Substring & prefix

    Given two strings, find the longest common subsequence (LCS). Your code should return the length of  ...

  9. Dynamic Programming | Set 4 (Longest Common Subsequence)

    首先来看什么是最长公共子序列:给定两个序列,找到两个序列中均存在的最长公共子序列的长度.子序列需要以相关的顺序呈现,但不必连续.例如,"abc", "abg", ...

随机推荐

  1. 现在就可以使用的5个 ES6 特性

    小编推荐:掘金是一个高质量的技术社区,从 ECMAScript 6 到 Vue.js,性能优化到开源类库,让你不错过前端开发的每一个技术干货.各大应用市场搜索「掘金」即可下载APP,技术干货尽在掌握. ...

  2. AE 开发添加新增字段 报错

    在为现有要素类新增字段时,有可能会爆出该表正被其他程序或其他人使用,这时我们就会添加失败,解决办法如下: 在新增字段之前,先修改SchemaLock的状态 ISchemaLock pSchemaLoc ...

  3. JS中的Math.pow(a,b)方法

    定义和用法 pow() 方法可返回 x 的 y 次幂的值. 语法 Math.pow(x,y) 参数 描述 x 必需.底数.必须是数字. y 必需.幂数.必须是数字. 返回值 x 的 y 次幂. 说明 ...

  4. python 字典dict和列表list的读取速度问题, range合并

    python 字典和列表的读取速度问题 最近在进行基因组数据处理的时候,需要读取较大数据(2.7G)存入字典中,然后对被处理数据进行字典key值的匹配,在被处理文件中每次读取一行进行处理后查找是否在字 ...

  5. 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:3.安装Oracle RAC-3.3.安装前检查

    3.3. 安装前检查 1.检查节点连通性 或:./runcluvfy.sh stage -pre crsinst -n linuxrac1,linuxrac2 -fixup -verbose [gri ...

  6. 手游产品经理初探(四)从Buybutton谈玩家付费

    付费模块一直是游戏中最最重要的一块,那么今天我们从玩家的角度来解说哪种方式付费更迎合玩家的心理.我还是着重从我做的Casino类型游戏说起. 一般来说游戏界面喜欢把付费button放在界面最醒目的位置 ...

  7. 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何让不同的PLC程序分线程运行 TC3

    右击Tasks,添加一个新的Task   可以为这个线程设置自定义的扫描周期   然后在项目上右击添加Referenced Task   在TaskSub1上右击添加现有项,把之气写好的PRG程序绑定 ...

  8. java 入门-helloWorld

    Java 教程 Java 是由Sun Microsystems公司于1995年5月推出的高级程序设计语言. Java可运行于多个平台,如Windows, Mac OS,及其他多种UNIX版本的系统. ...

  9. Github——Git设置及GitHub的使用

    把github上的help. First : 安装:ubuntu 下,终端输入命令: sudo apt-get install git-core git-gui git-doc Next : 设置SS ...

  10. mui 选项卡

    方法一:通过css 实现选项卡 <div id="slider" class="mui-slider"> <div id="slid ...