1 def list_or_update(x):
 2     return isinstance(x, (list, tuple))
 3 
 4 def flatten(sequence, to_expand=list_or_update):
 5     for item in sequence:
 6         if to_expand(item):
 7             for subitem in flatten(item, to_expand):
 8                 yield subitem
 9         else:
10             yield item
1 例如:一个字符串  awbcdewgh
2 
3 他的子串:  awbc、awbcd、awbcde   ...很多个子串 ,但是都是连续在一起 。//substring
4 
5 他的子序列:(subsequence ) abc 、abcd、 abcde  ...  很多个子序列 ,但是子序列中的字符在字符串中不一定是连在一起的,而是删除其中若干个, 但是子序列一定是单调的(即字符之间ASCII单调递增或单调递减,相对顺序不能改变)
6 
7 所以  子串!=子序列
def lengthoflis(nums):
    if not nums:
        return 0
    n = len(nums)
    dp = [1 for _ in range(n)]
    for i in range(1,n):
        for j in range(i):
            if nums[j] < nums[i]:
                dp[i] = max(dp[i],dp[j]+1)
    return max(dp)
def sub(arr):
    finish=[]    # the list containing all the subsequences of the specified sequence
    size = len(arr)    # the number of elements in the specified sequence
    end = 1 << size    # end=2**size
    for index in range(end):   
        array = []    # remember to clear the list before each loop
        for j in range(size):
            if (index >> j) % 2:    # this result is 1, so do not have to write ==
                array.append(arr[j])
        # print(array)
        finish.append(array)
    return finish
1 int LIS(int a[], int n)
 2 {
 3     int DP[n];
 4     int Cnt=-1;
 5     memset(DP, 0, sizeof(DP));
 6     for(int i=0; i<n; i++ ){
 7         for(int j=0; j<i; j++ ){
 8             if( a[i]>a[j] ){
 9                 DP[i] = max(DP[i], DP[j]+1);
10                 Cnt = max(DP[i], Cnt);//记录最长序列所含元素的个数
11             }
12         }
13     }
14     return Cnt+1;//因为初始化为0,所以返回结果+1
15 }
int n = array.length;
int[] dp = new int[n];

for (int i = 1; i < n; i++) {
    for (int j = 0; j < i; j++) {
        dp[i] = 最值(dp[i], dp[j] + ...)
    }
}
// q.c

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int M=1000000+10;
struct Data { 
	int x,y,z; 
	bool operator > (const Data &A) {
		if(x!=A.x) return x>A.x;
		if(y!=A.y) return y<A.y;
		return z<A.z;
	}
};
int n,a[M];
Data solve(int l,int r) {
	if(l==r) return (Data){a[l],l,r};
	int mid=(l+r)>>1,lsum=a[mid],rsum=a[mid+1];
	Data lc=solve(l,mid);
	Data rc=solve(mid+1,r);
	Data lp={a[mid],mid,mid};
	Data rp={a[mid+1],mid+1,mid+1};
	for(int i=mid-1;i>=l;lsum+=a[i],i--)
		if(lsum+a[i]>=lp.x) lp.x=lsum+a[i],lp.y=i;
	for(int i=mid+2;i<=r;rsum+=a[i],i++) 
		if(rsum+a[i]>rp.x) rp.x=rsum+a[i],rp.z=i;
	Data res={lp.x+rp.x,lp.y,rp.z};
	if(lc>res) res=lc;
	if(rc>res) res=rc;
	return res;
}
int main() {
	freopen("subq.in","r",stdin);
	freopen("subq.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	Data ans=solve(1,n);
	printf("%d\n%d\n%d\n",ans.y,ans.z,ans.x);
	return 0;
}
int n = array.length;
int[] dp = new int[n];

for (int i = 1; i < n; i++) {
    for (int j = 0; j < i; j++) {
        dp[i] = 最值(dp[i], dp[j] + ...)
    }
}
int len1, len2;
const int n = 1002;
int b[n][n];//b[i][j]表示c[i][j]的来源,用于输出最长公共子序列 为1时说明s1[i-1]=s2[j-1] 则可以递归函数print再输出s1[i-1]
//b[i][j]为2时说明s1[i-1]不等于s2[j-1] 最优解来源于c[i][j]=c[i][j-1] 递归输出print(i,j-1)
//为3时说明1[i-1]不等于s2[j-1] 最优解来源于c[i][j]=c[i-1][j] 递归输出print(i-1,j) i或者j为0时递归结束
int c[n][n];//c[len1][len2]表示最长公共子序列的长度
char s1[n], s2[n];

void LCSL() {

    for (int i = 1; i <= len1; i++) 
        for (int j = 1; j <= len2; j++) {
            if (s1[i - 1] == s2[j - 1]) {
                b[i][j] = 1;
                c[i][j] = c[i - 1][j - 1] + 1;
            }
            else if (c[i - 1][j] >= c[i][j - 1]) {
                b[i][j] = 2;
                c[i][j] = c[i - 1][j];
            }
            else {
                b[i][j] = 3;
                c[i][j] = c[i][j - 1];
            }
        }
    
}



        void print(int i, int j) {
            if (i == 0 || j == 0) return;
            if (b[i][j] == 1)
            {
                print(i - 1, j - 1);
                cout << s1[i - 1];
            }
            else if (b[i][j] == 2) {
                print(i - 1, j);
            }
            else
                print(i, j - 1);
        }
int main()

{
   
    cout << "input s1 and s2";
    cin >> s1;
    cout << "s2:";
    cin >> s2;
    len1 = strlen(s1);
    len2 = strlen(s2);
    for (int i = 0; i < len1; i++) {
        for (int j = 0; j < len2; j++) {
            c[0][j] = 0;
            c[i][0] = 0;
        }
    }
    LCSL();
    print(len1, len2);
}
class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        if s and t:  # 如果s或中有空字符串,立即返回false
            return False
        else:
	        N = len(t)  # t字符串的总长度
	        i = 0   # 表字符串开始匹配的位置
	        for j in s:  # 遍历s中每个字符
	            if i >= N:  # 字符匹配的位置不能超过子串的总长度
	                return False
	            if i not in t[i:j]:  # 判断s中的字符是否在t中
	                return False
	            else:
	                start = t.index(j,i,N) + 1  # 在t[j:N]字符串的中查找是有s的字符后立马向后查询
	        return True
#include <bits/stdc++.h>
using namespace std;
long long a[100005],f[100005],con[100005];
long long mod=1e9+7;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
f[0]=1;
for(int i=1;i<=n;i++)
{
f[i]=f[i-1]*2%mod;
if(con[a[i]])
{
f[i]=(f[i]-f[con[a[i]]-1]+mod)%mod;
}
con[a[i]]=i;
}
cout<<f[n]-1<<endl;
return 0;
}
public int lengthOfLIS(int[] nums) {
        //dp[i]: 到i为止 (对于所有 j in [0, i], 记录max length of increasing subsequence
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int len = nums.length;
        int[] dp = new int[len];
        int res = 0;
        for (int i = 0; i < len; i++) {
            dp[i] = 1;
            for (int j = 0; j < i; j++) {
                //i 位置的数与[0,i]位置之间的数比较,如果大于进逻辑
                if (nums[i] > nums[j]) {
                    //等于dp[i]或者dp[j] + 1(j对应的值比i小)的最大值
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9+7;
ll a[100010];
ll dp[100010];
ll vis[100010];
ll pos[100010];

int main()
{
int n;
cin>>n;
for(int i = 1; i <= n; i++)
{
scanf("%lld",&a[i]);
vis[i] = pos[a[i]];
pos[a[i]] = i;
}
dp[1] = 1;
for(int i = 2; i <= n; i++)
{
if(!vis[i])
{
dp[i] = dp[i-1]*2%mod+1;
dp[i] %= mod;
}
else
{
dp[i] = ((dp[i-1]*2+mod)-dp[vis[i]-1]%mod)%mod;
dp[i] %= mod;
}
if(dp[i] == 0)
dp[i] = (ll)1;
}
printf("%lld\n",dp[n]%mod);
}
1 for(i...a[]的长度)
2     for(j...b[]的长度)
3     {
4         dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
5             if(a[i] == b[j])
6                 dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
7     }
8     输出dp[a[]的长度][b[]的长度]
3 5
1 3 5
1 2 3 4 5
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

进阶:
如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码

示例 1:
输入:s = "abc", t = "ahbgdc"
输出:true

示例 2:
输入:s = "axc", t = "ahbgdc"
输出:false
flowchart TD
    A[开始] --> B[初始化子序列列表]
    B --> C[生成所有可能的子序列]
    C --> D[筛选符合条件的子序列]
    D --> E[输出结果]
    E --> F[结束]
 1   //dp解法
 2     bool isSubsequence(string s, string t){
 3         int n = s.length(),m = t.length();
 4         //dp数组dp[i][j]表示字符串t以i位置开始第一次出现字符j的位置
 5         vector<vector<int>> dp(m + 1,vector<int> (26,0));
 6 
 7         //初始化边界条件,dp[i][j] = m表示t中不存在字符j
 8         for(int i=0;i<26;i++){
 9             dp[m][i] = m;
10         }
11 
12         //从后往前递推初始化dp数组
13         for(int i = m - 1;i>=0;i--) {
14             for(int j=0;j<26;j++){
15                 if(t[i] == 'a' + j){
16                     dp[i][j] = i;
17                 }else {
18                     dp[i][j] = dp[i + 1][j];
19                 }
20             }
21         }
22 
23         int add = 0;
24         for(int i = 0;i<n;i++){
25             //t中没有s[i] 返回false
26             if(dp[add][s[i] - 'a'] == m){
27                 return false;
28             }
29             //否则直接跳到t中s[i]第一次出现的位置之后一位
30             add = dp[add][s[i] - 'a'] + 1;
31         }
32         return true;
33     }
#include <stdio.h>
#include <stdlib.h>
int main()
{
    int n,i,j;
    int a[1001],b[1001];
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0;i<=n-1;i++)
        {
            scanf("%d",&a[i]);
        }
        b[0]=a[0];
        for(i=1;i<=n-1;i++)
        {
            int sum=0;
            for(j=0;j<i;j++)
            {
                if(a[i]>a[j]&&sum<b[j])
                {
                    sum=b[j];
                }
                b[i]=sum+a[i];
            }

        }
        int max=b[0];
        for(i=1;i<=n-1;i++)
        {
            if(b[i]>max)
            {
                max=b[i];
            }
        }
        printf("%d\n",max);
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5