美团笔试-小美的子序列-动态规划

小美的子序列

小美在n行m列的本子上写了许多字母,她会在每一行中找出一个字母,然后组成一个字符串。

小美想知道,组成的字符串中是否存在至少一个字符串包含 "meituan" 子序列。

输入描述

第一行输入2个整数n,m(1<=n,m<=1000) 。

接下来n行,每行输入一个长度为m的字符串表示小美写下的字母。

输出描述

若存在至少一个字符串包含 "meituan" 子序列,则输出 "YES",否则输出 "NO"。

示例1

输入

3 3
abc
def
ghi

输出

NO

说明

显然并不能找到meituan子序列。

示例2

输入

8 2
nm
ex
it
td
ul
qu
ac
nt

输出

YES

说明

第1行选择第2个字母。
第2行选择第1个字母。
第3行选择第1个字母。
第4行选择第1个字母。
第5行选择第2个字母。
第6行选择第2个字母。
第7行选择第1个字母。
第8行选择第1个字母。
组成字符串"meitluan",其中存在"meituan"子序列。
当然,第6行选第1个字母且第5行选第1个字母组成的字符串"meituqan"中也存在"meituan"子序列。

思路:

i在这里的含义是第i个输入的字符串,j为 meituqan 这八个字母的其中之一

我们定义一个二维数组 ext[i][j] 为字母j是否在第i个字符串中存在,然后遍历所有输入的字符串,标记所有的ext

接着我们定义dp[i][j] 为 在前i个字符串中,结尾为j的字母是否被满足,

当dp[i-1][j] = true时,意味着在之前一个字符串中就已经满足了以j为结尾的 meituqan 字符串了,所以 dp[i][[j]可以直接继承他的状态

当dp[i-1][j]!=true时,意味着先前没有满足 以j为结尾的 meituqan 字符串,那么 dp[i][j]的状态就取决于 dp[i-1][j-1] && ext[j][j] 即(上一个输入的字符串是否满足 j前面那个字符为结尾的字符串)&& (在第i个输入的字符串中是否存在j)

我们可以得出转移方程

dp[i][j] = dp[i-1][j] || ( ext[i][j] && dp[i-1][j-1] )

在初始化阶段 dp[i][0] 的状态完全由ext[i][0]决定,因为此时 j 只有一个字符串,没有前面的状态,出现输入的字符串中就说明他是true,否则为false

代码

import java.util.Scanner;
import java.util.Stack;

public class Main {
    private static final int MAXN = 10005;


    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        sc.nextLine();
        String[] s = new String[n+1];

        for(int i=1;i<=n;i++){
            s[i] = sc.nextLine();
        }

        boolean[][] ext = new boolean[MAXN][7]; // 字母j在i行是否存在
        boolean[][] dp = new boolean[MAXN][7];

        for(int i = 1;i<=n;i++){
            for(int j=1;j<=m;j++){
                char c = s[i].charAt(j-1);
                int t = decode(c);
                if(t>=0){
                    ext[i][t] = true;
                }
            }
        }

        for(int i=1;i<=n;i++){
            for(int j=0;j<7;j++){
                if(j==0){
                    if(ext[i][j]){
                        dp[i][j] = true;
                    }else{
                        dp[i][j] = false;
                    }
                    continue;
                }
//                dp[i][j] = dp[i-1][j];
                if(ext[i][j]){
                    dp[i][j] = dp[i-1][j-1] || dp[i-1][j];
                }else{
                    dp[i][j] = dp[i-1][j];
                }

            }
        }

        System.out.println(dp[n][6]? "YES":"NO");

    }

    public static int decode(char c){
        switch (c){
            case 'm':
                return 0;
            case 'e':
                return 1;
            case 'i':
                return 2;
            case 't':
                return 3;
            case 'u':
                return 4;
            case 'a':
                return 5;
            case 'n':
                return 6;
        }
        return -1;
    }


}

猜你喜欢

转载自blog.csdn.net/qq_51118755/article/details/132792540