首先需要知道,子串和子序列的概念,我们以字符子串和字符子序列为例,更为形象,也能顺带着理解字符的子串和子序列:
(1)字符子串指的是字符串中连续的n个字符,如abcdefg中,ab,cde,fg等都属于它的字串。
(2)字符子序列指的是字符串中不一定连续但先后顺序一致的n个字符,即可以去掉字符串中的部分字符,但不可改变其前后顺序。如abcdefg中,acdg,bdf属于它的子序列,而bac,dbfg则不是,因为它们与字符串的字符顺序不一致。
O(n^2)的DP,O(nlogn)的二分+贪心法,以及O(nlogn)的树状数组优化的DP。
O(n^2)暴力DP
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 int n; 6 int a[1010],f[1010]; 7 int main() { 8 cin>>n; 9 a[0]=-2000000000; 10 for(int i=1; i<=n; i++) cin>>a[i]; 11 for(int i=1; i<=n; i++) 12 for(int j=0; j<i; j++) 13 if(a[j]<a[i]) f[i]=max(f[i],f[j]+1); 14 int ans=0; 15 for(int i=1; i<=n; i++) ans=max(ans,f[i]); 16 cout<<ans<<endl; 17 return 0; 18 }
O(nlongn)二分+贪心,lower_bound
1 #include<bits/stdc++.h> 2 #define N 100010 3 using namespace std; 4 5 int n; 6 int a[N],q[N]; 7 int main() { 8 cin>>n; 9 for(int i=1; i<=n; i++) cin>>a[i]; 10 int len=0; 11 q[1]=-2e9; 12 for(int i=1; i<=n; i++) { 13 int l=1,r=len+1; 14 while(l<r) { 15 int mid=l+r+1>>1; 16 if(q[mid]<a[i]) l=mid; 17 else r=mid-1; 18 } 19 len=max(len,r); 20 q[r+1]=a[i]; 21 } 22 cout<<len<<endl; 23 return 0; 24 }
1 #include<bits/stdc++.h> 2 #define N 100010 3 using namespace std; 4 5 int n; 6 int a[N],q[N]; 7 int main() { 8 cin>>n; 9 for(int i=1; i<=n; i++) cin>>a[i]; 10 int len=0; 11 q[1]=-2e9; 12 for(int i=1; i<=n; i++) { 13 int k=lower_bound(q+1,q+len+2,a[i])-q-1; 14 len=max(len,k); 15 q[k+1]=a[i]; 16 } 17 cout<<len<<endl; 18 return 0; 19 }
求出具体的数字(倒序输出)
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 int n; 6 int a[1010],f[1010],g[1010]; 7 int main() { 8 cin>>n; 9 a[0]=-2000000000; 10 for(int i=1; i<=n; i++) cin>>a[i]; 11 for(int i=1; i<=n; i++) 12 for(int j=0; j<i; j++) 13 if(a[j]<a[i]) 14 if(f[i]<f[j]+1) g[i]=j,f[i]=f[j]+1; 15 int k=1; 16 for(int i=1; i<=n; i++) 17 if(f[i]>f[k]) k=i; 18 cout<<f[k]<<endl; 19 for(int i=1,len=f[k]; i<=len; i++) cout<<a[k]<<" ",k=g[k]; 20 return 0; 21 }
Dilworth定理


浙公网安备 33010602011771号