LIS O(n^2)算法:
1 for(int i=1;i<=n;i++){ 2 for(int j=1;j<i;i++){ 3 if(arr[i]>arr[j]) 4 d[i]=max(d[i],d[j]+1); 5 ] 6 ]
LIS O(nlogn)算法:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=1e5+5; 5 int a[maxn]; 6 int n; 7 int lis[maxn]; 8 int len=1; 9 int find(int x){ 10 int l=1,r=len,m; 11 while(l<r){ 12 m=l+(r-l)/2; 13 if(lis[m]>=a[x]){//这里若去掉等号即为 非严格递增序列 14 r=m; 15 } 16 else{ 17 l=m+1; 18 } 19 } 20 return l; 21 } 22 int main(void){ 23 scanf("%d",&n); 24 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 25 lis[1]=a[1]; 26 for(int i=2;i<=n;i++){ 27 if(a[i]>lis[len]){ 28 lis[++len]=a[i]; 29 } 30 else{ 31 int pos=find(i); 32 lis[pos]=a[i]; 33 } 34 } 35 printf("%d",len); 36 return 0; 37 }
LCS O(n^2)算法:
1 for(int i=1;i<=n;i++){ 2 for(int j=1;j<=n;j++){ 3 if(a[i]==b[i]) 4 d[i][j]=max(d[i]j],d[i-1][j-1]); 5 else 6 d[i][j]=max(d[i-1][j],d[i][j-1]); 7 } 8 }
LCS O(nlogn)算法:
最长公共子序列 的 nlogn 的算法本质是 将该问题转化成 最长增序列(LIS),因为 LIS 可以用nlogn实现,所以求LCS的时间复杂度降低为 nlogn。
假设有两个序列 s1[ 1~6 ] = { a, b, c , a, d, c }, s2[ 1~7 ] = { c, a, b, e, d, a, b }。
记录s1中每个元素在s2中出现的位置, 再将位置按降序排列, 则上面的例子可表示为:
loc( a)= { 6, 2 }, loc( b ) = { 7, 3 }, loc( c ) = { 1 }, loc( d ) = { 5 }。
将s1中每个元素的位置按s1中元素的顺序排列成一个序列s3 = { 6, 2, 7, 3, 1, 6, 2, 5, 1 }。
在对s3求LIS得到的值即为求LCS的答案。
(上述文字及nlogn代码来自于https://www.cnblogs.com/KYSpring/p/9021909.html)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 using namespace std; 5 const int maxn=1e6+5; 6 int n,len=0; 7 int lis[maxn]; 8 int a[maxn]; 9 int b[maxn]; 10 int loc[maxn]; 11 int find(int x){ 12 int l=1,r=len,m; 13 while(l<r){ 14 m=l+(r-l)/2; 15 //if(lis[m]>=b[x]){//智障错误,找了那么久。。 16 if(lis[m]>=x){ 17 r=m; 18 } 19 else l=m+1; 20 } 21 return l; 22 } 23 int main(void){ 24 scanf("%d",&n); 25 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 26 for(int i=1;i<=n;i++){ 27 scanf("%d",&b[i]); 28 loc[b[i]]=i; 29 } 30 for(int i=1;i<=n;i++){ 31 b[i]=loc[a[i]]; 32 } 33 // for(int i=1;i<=n;i++)printf("%d",b[i]) ;// 34 // printf("\n"); 35 if(n!=0)lis[++len]=b[1]; 36 for(int i=2;i<=n;i++){ 37 if(b[i]>lis[len]){ 38 lis[++len]=b[i]; 39 } 40 else{ 41 int pos=find(b[i]); 42 lis[pos]=b[i]; 43 } 44 } 45 printf("%d",len); 46 return 0; 47 }
保存路径:
1 #include<stdio.h> 2 #include<string.h> 3 #include<stack> 4 #include<algorithm> 5 using namespace std; 6 #define N 1010 7 int dp[N][N]; 8 char c; 9 int main() 10 { 11 char a[N]; 12 char b[N]; 13 scanf("%s%s",a,b); 14 int la=strlen(a); 15 int lb=strlen(b); 16 memset(dp,0,sizeof(dp)); 17 for(int i=1; i<=la; i++) 18 { 19 for(int j=1; j<=lb; j++) 20 { 21 if(a[i-1]==b[j-1]) 22 dp[i][j]=dp[i-1][j-1]+1; 23 else 24 dp[i][j]=max(dp[i-1][j],dp[i][j-1]); 25 } 26 } 27 int i=la,j=lb; 28 stack<char>s; 29 while(dp[i][j]) 30 { 31 if(dp[i][j]==dp[i-1][j])///来自于左方向 32 { 33 i--; 34 } 35 else if(dp[i][j]==dp[i][j-1])///来自于上方向 36 { 37 j--; 38 } 39 else if(dp[i][j]>dp[i-1][j-1])///来自于左上方向 40 { 41 i--; 42 j--; 43 s.push(a[i]); 44 } 45 } 46 while(!s.empty()) 47 { 48 c=s.top(); 49 printf("%c",c); 50 s.pop(); 51 } 52 return 0; 53 }
最长公共字串:
1)暴力:
1 int longestSubstring(string x, string y) { 2 int max = 0; 3 string str = ""; 4 for (int i = 0; i < x.size(); i++) { 5 int len = 0; 6 int j = i; 7 while (j < x.size()) { 8 str += x[j]; 9 if (y.find(str) == y.npos) break; 10 len++; 11 j++; 12 if (len > max) max = len; 13 } 14 str = ""; 15 } 16 return max; 17 }
2)动态规划:
1 int longestSubstring(string x, string y) { 2 vector<vector<int> > f(x.size() + 1, vector<int>(y.size() + 1, 0)); 3 int max = -1; 4 for (int i = 1; i <= x.size(); i++) { 5 for (int j = 1; j <= y.size(); j++) { 6 if (x[i - 1] != y[j - 1]) f[i][j] = 0; 7 else if (x[i - 1] == y[j - 1]) f[i][j] = f[i - 1][j - 1] + 1; 8 if (max < f[i][j]) { 9 max = f[i][j]; 10 } 11 } 12 } 13 return max; 14 }
原文:https://www.cnblogs.com/gn1314/p/11569928.html