LCS、LIS

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

扫描二维码关注公众号,回复: 7336597 查看本文章
 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 }

猜你喜欢

转载自www.cnblogs.com/gn1314/p/11569928.html