LCS LIS LCIS 算法
2016-01-15 21:07
726 查看
(这么久了,才开始写题解,我也是够懒) 先是LCS(最长公共子序列),例题么(COGS 476,我知道这个很水),先来划分阶段:A中前i个字符,B中前J个字符。然后是状态:定义:f[i][j]为A中前i个字符和B中前J个字符的最长公共子序列。那么只有两种状态:相同&不同。决策:若相同则f[i][j]=f[i-1][j-1]+1;若不同则从I或j中去一个求最大值f[i][j]=max(f[i][j-1],f[i-1][j]);(动归三步走)
for(int i=1;i<=l1;i++){//l1 l2 分别为两个字符串长度 for(int j=1;j<=l2;j++){ if(s1[i]==s2[j])f[i][j]=f[i-1][j-1]+1; else f[i][j]=max(f[i-1][j],f[i][j-1]); ans=max(ans,f[i][j]); } }
然后是LIS(最长上升子序列): n^2算法:对于下标i,A中前i位的最长上升子序列长度为以i之前下标为结尾的最长上升子序列的最大值当然结尾点的位置储存的数应当比i处储存的数要小。
小技巧:可以一边读入一遍计算;
for(int i=1;i<=n;i++){ scanf("%d",&a[i]); f[i]=1;//f[i]是到下标i最长上升子序列的长度; for(int j=1;j<i;j++){ if(a[j]<a[i])f[i]=max(f[j]+1,f[i]); } ans=max(ans,f[i]);//保存最大解; }
nlogn算法:
保存最长上升子序列每一位上的最小值,那么对于以后的数,若对于一个数x,他比len位上的数大说明他可以构成一个长度为len+1长的上升序列,在此期间不断维护每一位上的数是这一位上的最小值,因满足单调性故查找时可以使用二分优化。
len=1;c[len]=a[1]; for(int i=2;i<=n;++i){ if(a[i]>c[len]) c[++len]=a[i]; else{ l=1,r=len; while(l<=r){ int mid=(l+r)>>1; if(c[mid]<a[i]) l=mid+1; else r=mid-1; } c[l]=a[i]; } }
LCIS(最长公共上升子序列):
例题:cogs 1669 神秘的咒语;
与LIS大致相同但是LCIS只有当两个字符串中某位置和某位置相等时才去查找之前的。
for(int i=1;i<=n;i++){ ans=0; for(int j=1;j<=m;j++){ f[i][j]=f[i-1][j]; if(num1[i]==num2[j])f[i][j]=ans+1; if(num1[i]>num2[j]&&ans<f[i-1][j])ans=f[i-1][j]; } }
只敲一些片段可能看不懂,那就结合例题喽:
COGS 476:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; char s1[5005],s2[5005]; int f[5005][5005],l1,l2,ans; int main(){ //freopen("lcslength.in","r",stdin); //freopen("lcslength.out","w",stdout); scanf("%s%s",s1+1,s2+1); l1=strlen(s1+1)-1,l2=strlen(s2+1)-1,ans=0; for(int i=1;i<=l1;i++){ for(int j=1;j<=l2;j++){ if(s1[i]==s2[j])f[i][j]=f[i-1][j-1]+1; else f[i][j]=max(f[i-1][j],f[i][j-1]); ans=max(ans,f[i][j]); } } printf("%d\n",ans); return 0; }
COGS 1398:
n^2:
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; int a[1001],f[1001]; int main(){ //freopen("lis1.in","r",stdin); //freopen("lis1.out","w",stdout); int n,ans=0; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); f[i]=1; for(int j=1;j<i;j++){ if(a[j]<a[i])f[i]=max(f[j]+1,f[i]); } ans=max(ans,f[i]); } printf("%d",ans); return 0; }
nlogn:
#include<cstdio>
using namespace std;
int n,len,a[1005],c[1005],l,r;
inline void get1(int &x)
{
char ch;
while(ch=getchar(),ch<48||ch>57);
x=ch-48;
while(ch=getchar(),ch>47&&ch<58)x=x*10+ch-48;
}
int main(){
freopen("lis1.in","r",stdin);
freopen("lis1.out","w",stdout);
get1(n);
for(int i=1;i<=n;++i) get1(a[i]);
len=1;c[len]=a[1]; for(int i=2;i<=n;++i){ if(a[i]>c[len]) c[++len]=a[i]; else{ l=1,r=len; while(l<=r){ int mid=(l+r)>>1; if(c[mid]<a[i]) l=mid+1; else r=mid-1; } c[l]=a[i]; } }
printf("%d",len);
return 0;
}
//7
//1 7 3 5 9 4 8
COGS 1669:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int num1[505],num2[505],n,m,t,f[505][505],ans; int main(){ freopen("codes.in","r",stdin); freopen("codes.out","w",stdout); scanf("%d",&t); while(t--){ memset(num1,0,sizeof(num1)); memset(num2,0,sizeof(num2)); memset(f,0,sizeof(f)); ans=0; scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&num1[i]); scanf("%d",&m); for(int i=1;i<=m;i++)scanf("%d",&num2[i]); for(int i=1;i<=n;i++){ ans=0; for(int j=1;j<=m;j++){ f[i][j]=f[i-1][j]; if(num1[i]==num2[j])f[i][j]=ans+1; if(num1[i]>num2[j]&&ans<f[i-1][j])ans=f[i-1][j]; } } ans=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ ans=max(ans,f[i][j]); } } printf("%d",ans); if(t)printf("\n"); } return 0; }
相关文章推荐
- 第七章 ReentrantLock总结
- Codeforces Round #339 (Div. 2) B. Gena's Code
- BZOJ 2762: [JLOI2011]不等式组( 平衡树 )
- Space Elevator(DP)
- VS2012下C++操作word(整理)
- LCT(Link Cut Tree)学习小记
- PHP 生成唯一编码字符的方法
- intl PHP extension is not working for windows解决方法
- cocos2d-x类型转换(CCstring int string char UTF-8互转)
- 数据结构之数组和字符串的反转java实现
- 计算机网络的形象解释
- 计网-ch05-题目与解释
- 池化方法总结
- HTML—JavaScript基础(三)
- html 高亮显示表格当前行
- 《云计算架构技术与实践》连载15:2.3.2~2.3.6 弹性伸缩、高性能、用户体验、高安全、高可靠
- 【bzoj2242】[SDOI2011]计算器 快速幂+exgcd+BSGS
- Codeforces Round #339 (Div. 2) B.Gena's Code
- 格式化数据#3:有关逻辑推理/语义的资源
- css015 定位网页上的元素