[左神面试指南] 字符串[下]篇

CD126 括号字符串的有效性

/* 模拟 */
public class CD126_1
{
    public static String solution(String s)
    {
        int l = 0, r = 0;
        for (char ch : s.toCharArray())
        {
            if (ch == '(' || ch == ')')
            {
                if (ch == '(') l++;
                else r++;
            }
            else return "NO";
            if (r > l) return "NO";
        }
        return r == l ? "YES" : "NO";
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String s;
        s = in.nextLine();
        System.out.println(solution(s));
    }
}

CD127 括号字符串的最长有效长度⭐

/* ⭐DP⭐
 * dp[i]表示为: str[0..i]中以字符str[i]结尾的最长的有效括号子串长度
 */
public class CD127_1
{
    public static int solution(String s)
    {
        int ans = 0;
        int[] dp = new int[s.length()];
        for (int i = 1; i < s.length(); i++)
        {
            if (s.charAt(i) == '(') continue;
            int pre = i - dp[i - 1] - 1;
            if (pre >= 0 && s.charAt(pre) == '(')
            {
                dp[i] = dp[i - 1] + 2 + (pre > 0 ? dp[pre - 1] : 0);
                ans = Math.max(ans, dp[i]);
            }
        }
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String s;
        s = in.nextLine();
        System.out.println(solution(s));
    }
}

/* ⭐栈⭐ */
public class CD127_2
{
    public static int solution(String s)
    {
        int maxans = 0;
        Stack<Integer> stack = new Stack<Integer>();
        stack.push(-1);
        for (int i = 0; i < s.length(); i++)
        {
            if (s.charAt(i) == '(')
                stack.push(i);
            else
            {
                stack.pop();
                if (stack.isEmpty())
                    stack.push(i);
                else
                    maxans = Math.max(maxans, i - stack.peek());
            }
        }
        return maxans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String s;
        s = in.nextLine();
        System.out.println(solution(s));
    }
}

CD128 公式字符串求值

/* 模拟 */
public class CD128_1
{
    public static int solution(String s)
    {
        return cal(s, 0)[0];
    }

    private static int[] cal(String s, int idx)
    {
        Stack<Integer> nums = new Stack<>();
        nums.add(0);
        Stack<Character> ops = new Stack<>();
        for (int i = idx; i < s.length(); i++)
        {
            if (Character.isDigit(s.charAt(i)))
            {
                int num = s.charAt(i) - '0';
                while (i + 1 < s.length() && Character.isDigit(s.charAt(i + 1)))
                {
                    num = num * 10 + s.charAt(i + 1) - '0';
                    i++;
                }
                nums.add(num);
            }
            else if (s.charAt(i) == '(')
            {
                int[] res = cal(s, i + 1);
                nums.add(res[0]);
                i = res[1];
            }
            else if (s.charAt(i) == ')')
            {
                while (!ops.isEmpty())
                    calNum(nums, ops);
                return new int[]{nums.pop(), i};
            }
            else
            {
                while (!ops.isEmpty() && order(s.charAt(i)) <= order(ops.peek()))
                    calNum(nums, ops);
                ops.add(s.charAt(i));
            }
        }
        while (!ops.isEmpty())
            calNum(nums, ops);
        return new int[]{nums.pop(), -1};
    }

    public static void calNum(Stack<Integer> nums, Stack<Character> ops)
    {
        int last = nums.pop(), pre = nums.pop();
        char op = ops.pop();
        switch (op)
        {
            case '+':
                nums.add(pre + last);
                break;
            case '-':
                nums.add(pre - last);
                break;
            case '*':
                nums.add(pre * last);
                break;
            case '/':
                nums.add(pre / last);
                break;
        }
    }

    public static int order(char ch)
    {
        if (ch == '+' || ch == '-') return 0;
        else return 1;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String s;
        s = in.nextLine();
        System.out.println(solution(s));
    }
}

/* 单调队列 */
public class CD128_2
{
    public static int solution(String s)
    {
        Stack<Integer> nums = new Stack<>();
        Stack<Character> ops = new Stack<>();
        nums.add(0);
        for (int i = 0; i < s.length(); i++)
        {
            if (Character.isDigit(s.charAt(i)))
            {
                int num = s.charAt(i) - '0';
                while (i + 1 < s.length() && Character.isDigit(s.charAt(i + 1)))
                    num = num * 10 + s.charAt(++i) - '0';
                nums.add(num);
            }
            else
            {
                char op = s.charAt(i);
                while (check(ops, op))
                    calNum(nums, ops);
                if (op != ')')
                    ops.add(op);
            }
        }
        while (!ops.isEmpty())
            calNum(nums, ops);
        return nums.pop();
    }

    private static boolean check(Stack<Character> ops, char op)
    {
        if (ops.isEmpty() || op == '(') return false;
        int topOp = order(ops.peek()), newOp = order(op);
        if (newOp == 0)
        {
            if (topOp == 1)
            {
                ops.pop();
                return false;
            }
            else return true;
        }
        return newOp <= topOp;
    }


    public static void calNum(Stack<Integer> nums, Stack<Character> ops)
    {
        int last = nums.pop(), pre = nums.pop();
        char op = ops.pop();
        switch (op)
        {
            case '+':
                nums.add(pre + last);
                break;
            case '-':
                nums.add(pre - last);
                break;
            case '*':
                nums.add(pre * last);
                break;
            case '/':
                nums.add(pre / last);
                break;
        }
    }

    public static int order(char ch)
    {
        if (ch == '(') return 1;
        else if (ch == '+' || ch == '-') return 2;
        else if (ch == '*' || ch == '/') return 3;
        else return 0;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String s;
        s = in.nextLine();
        System.out.println(solution(s));
    }
}

CD129 0 左边必有 1 的二进制字符串数量

/* [f(n-1), f(n)] = [1, 2] * [[0, 1], [1, 1]]^(n-2)= */
public class CD129_1
{
    public static long solution(int n)
    {
        if (n < 1) return 0;
        if (n <= 2) return n;
        long[][] base = new long[][]{{0, 1}, {1, 1}};
        long[][] res = quick(base, n - 2, (int) Math.pow(2, 29));
        return (res[0][1] + 2 * res[1][1]) % (int) Math.pow(2, 29);
    }

    public static long[][] quick(long[][] base, int n, int MOD)
    {
        long[][] ans = new long[][]{{1, 0}, {0, 1}};
        while (n != 0)
        {
            if ((n & 1) == 1)
                ans = matrixMul(ans, base, MOD);
            base = matrixMul(base, base, MOD);
            n >>= 1;
        }
        return ans;
    }

    public static long[][] matrixMul(long[][] ans, long[][] base, int MOD)
    {
        long[][] res = new long[ans.length][base[0].length];
        for (int i = 0; i < ans.length; i++)
            for (int j = 0; j < base[0].length; j++)
                for (int k = 0; k < ans[0].length; k++)
                    res[i][j] = (res[i][j] + ans[i][k] * base[k][j]) % MOD;
        return res;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        System.out.println(solution(n));
    }
}

CD130 拼接所有字符串产生字典顺序最小的大写字符串⭐

/*⭐贪心⭐*/
public class CD130_1
{
    public static String solution(ArrayList<String> list)
    {
        Collections.sort(list, (o1, o2) -> (o1 + o2).compareTo(o2 + o1));
        return list.stream().collect(Collectors.joining(""));
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        ArrayList<String> list = new ArrayList<>();
        n = Integer.parseInt(in.nextLine());
        while (n-- > 0)
            list.add(in.nextLine());
        System.out.println(solution(list));
    }
}

CD131 找到字符串的最长无重复字符子串

/* 滑动窗口 */
public class CD131_1
{
    public static int solution(int[] arr)
    {
        int l = 0, r = 0, ans = Integer.MIN_VALUE;
        HashSet<Integer> map = new HashSet<>();
        while (r < arr.length)
        {
            while (r < arr.length && !map.contains(arr[r]))
            {
                map.add(arr[r++]);
                ans = Math.max(r - l, ans);
            }
            map.remove(arr[l]);
            l++;
        }
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr));
    }
}

CD132 找到指定的新类型字符

/* 模拟 */
public class CD132_1
{
    public static String solution(String s, int k)
    {
        k++;
        int sum = 0;
        for (int i = 0; i < s.length(); i++)
        {
            if (Character.isLowerCase(s.charAt(i)))
            {
                sum++;
                if (sum >= k) return s.substring(i, i + 1);
            }
            else
            {
                sum += 2;
                if (sum >= k) return s.substring(i, i + 2);
                i++;
            }
        }
        return "";
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n, k;
        String s;
        String[] temp = in.nextLine().split(" ");
        n = Integer.parseInt(temp[0]);
        k = Integer.parseInt(temp[1]);
        s = in.nextLine();
        System.out.println(solution(s, k));
    }
}

CD133 旋变字符串问题❗

/*❗❗*/
public class CD133_1
{
    public static boolean isScramble1(String s1, String s2)
    {
        if ((s1 == null && s2 != null) || (s1 != null && s2 == null)) return false;
        if (s1 == null && s2 == null) return true;
        if (s1.equals(s2)) return true;
        char[] str1 = s1.toCharArray();
        char[] str2 = s2.toCharArray();
        if (!sameTypeSameNumber(str1, str2)) return false;
        int N = s1.length();
        return process(str1, str2, 0, 0, N);
    }

    public static boolean sameTypeSameNumber(char[] str1, char[] str2)
    {
        if (str1.length != str2.length) return false;
        int[] map = new int[256];
        for (int i = 0; i < str1.length; i++)
            map[str1[i]]++;
        for (int i = 0; i < str2.length; i++)
            if (--map[str2[i]] < 0)
                return false;
        return true;
    }

    public static boolean process(char[] str1, char[] str2, int L1, int L2, int size)
    {
        if (size == 1) return str1[L1] == str2[L2];
        for (int leftPart = 1; leftPart < size; leftPart++)
        {
            if ((process(str1, str2, L1, L2, leftPart) && process(str1, str2, L1 + leftPart, L2 + leftPart, size - leftPart))
                    ||
                    (process(str1, str2, L1, L2 + size - leftPart, leftPart) && process(str1, str2, L1 + leftPart, L2, size - leftPart)))
                return true;
        }
        return false;
    }

    public static boolean isScramble2(String s1, String s2)
    {
        if ((s1 == null && s2 != null) || (s1 != null && s2 == null)) return false;
        if (s1 == null && s2 == null) return true;
        if (s1.equals(s2)) return true;
        char[] str1 = s1.toCharArray();
        char[] str2 = s2.toCharArray();
        if (!sameTypeSameNumber(str1, str2)) return false;
        int N = s1.length();
        boolean[][][] dp = new boolean[N][N][N + 1];
        // base case
        for (int L1 = 0; L1 < N; L1++)
            for (int L2 = 0; L2 < N; L2++)
                dp[L1][L2][1] = str1[L1] == str2[L2];
        for (int size = 2; size <= N; size++)
            for (int L1 = 0; L1 <= N - size; L1++)
                for (int L2 = 0; L2 <= N - size; L2++)
                    for (int leftPart = 1; leftPart < size; leftPart++)
                        if ((dp[L1][L2][leftPart] && dp[L1 + leftPart][L2 + leftPart][size - leftPart])
                                ||
                                (dp[L1][L2 + size - leftPart][leftPart] && dp[L1 + leftPart][L2][size - leftPart]))
                        {
                            dp[L1][L2][size] = true;
                            break;
                        }
        return dp[0][0][N];
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String s1, s2;
        s1 = in.nextLine();
        s2 = in.nextLine();
        System.out.println(isScramble2(s1, s2) ? "YES" : "NO");
    }
}

CD134 最小包含子串的长度

/* 滑动窗口 */
public class CD134_1
{

    public static int solution(String s1, String s2)
    {
        int l = 0, r = 0, ans = Integer.MAX_VALUE, match = s2.length();
        int[] map = new int[256];
        for (char ch : s2.toCharArray())
            map[ch]++;
        while (r < s1.length())
        {
            while (r < s1.length() && match != 0)
            {
                map[s1.charAt(r)]--;
                if (map[s1.charAt(r)] >= 0) match--;
                r++;
            }
            if (match == 0)
                ans = Math.min(ans, r - l);
            map[s1.charAt(l)]++;
            if (map[s1.charAt(l)] > 0) match++;
            l++;
        }
        return ans == Integer.MAX_VALUE ? 0 : ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String s1, s2;
        s1 = in.nextLine();
        s2 = in.nextLine();
        System.out.println(solution(s1, s2));
    }
}

CD135 回文最少分割数❗

/* ❗DP❗
 * dp[i]表示为子串str[i..len-1]至少需要切割几次, 才能把str[i..len-1]全部切成回文子串
 */
public class CD135_1
{
    public static int solution(String s)
    {
        int[] dp = new int[s.length() + 1];
        dp[s.length()] = -1;
        boolean[][] isSym = new boolean[s.length()][s.length()];
        for (int i = s.length() - 1; i >= 0; i--)
        {
            dp[i] = Integer.MAX_VALUE;
            for (int j = i; j < s.length(); j++)
            {
                if (s.charAt(i) == s.charAt(j) && (j - i < 2 || isSym[i + 1][j - 1]))
                {
                    isSym[i][j] = true;
                    dp[i] = Math.min(dp[i], dp[j + 1] + 1);
                }
            }
        }
        return dp[0];
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String s;
        s = in.nextLine();
        System.out.println(solution(s));
    }
}

CD136 字符串匹配问题❗

/*❗❗*/
public class CD136_1
{
    public static boolean isValid(char[] s, char[] e)
    {
        for (int i = 0; i < s.length; i++)
            if (s[i] == '*' || s[i] == '.')
                return false;
        for (int i = 0; i < e.length; i++)
            if (e[i] == '*' && (i == 0 || e[i - 1] == '*'))
                return false;
        return true;
    }

    public static boolean process(char[] s, char[] e, int si, int ei)
    {
        if (ei == e.length) return si == s.length;
        if (ei + 1 == e.length || e[ei + 1] != '*')
            return si != s.length
                    && (e[ei] == s[si] || e[ei] == '.')
                    && process(s, e, si + 1, ei + 1);
        while (si != s.length && (e[ei] == s[si] || e[ei] == '.'))
        {
            if (process(s, e, si, ei + 2))
                return true;
            si++;
        }
        return process(s, e, si, ei + 2);
    }

    public static boolean isMatch(String str, String exp)
    {
        if (str == null || exp == null) return false;
        char[] s = str.toCharArray();
        char[] e = exp.toCharArray();
        return isValid(s, e) && process(s, e, 0, 0);
    }

    public static boolean isMatchDP(String str, String exp)
    {
        if (str == null || exp == null) return false;
        char[] s = str.toCharArray();
        char[] e = exp.toCharArray();
        if (!isValid(s, e)) return false;
        boolean[][] dp = initDPMap(s, e);
        for (int i = s.length - 1; i > -1; i--)
        {
            for (int j = e.length - 2; j > -1; j--)
            {
                if (e[j + 1] != '*')
                    dp[i][j] = (s[i] == e[j] || e[j] == '.') && dp[i + 1][j + 1];
                else
                {
                    int si = i;
                    while (si != s.length && (s[si] == e[j] || e[j] == '.'))
                    {
                        if (dp[si][j + 2])
                        {
                            dp[i][j] = true;
                            break;
                        }
                        si++;
                    }
                    if (dp[i][j] != true)
                        dp[i][j] = dp[si][j + 2];
                }
            }
        }
        return dp[0][0];
    }

    public static boolean[][] initDPMap(char[] s, char[] e)
    {
        int slen = s.length;
        int elen = e.length;
        boolean[][] dp = new boolean[slen + 1][elen + 1];
        dp[slen][elen] = true;
        for (int j = elen - 2; j > -1; j = j - 2)
        {
            if (e[j] != '*' && e[j + 1] == '*')
                dp[slen][j] = true;
            else
                break;
        }
        if (slen > 0 && elen > 0)
        {
            if ((e[elen - 1] == '.' || s[slen - 1] == e[elen - 1]))
                dp[slen - 1][elen - 1] = true;
        }
        return dp;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        String s1, s2;
        s1 = in.nextLine();
        s2 = in.nextLine();
        System.out.println(isMatch(s1, s2) ? "YES" : "NO");
    }
}

CD140 字典树(前缀树)的实现

/* 字典树 */
public class CD140_1
{
    public static class TrieNode
    {
        public int path;
        public int end;
        public TrieNode[] map;

        public TrieNode()
        {
            path = 0;
            end = 0;
            map = new TrieNode[26];
        }
    }

    public static class Trie
    {
        private TrieNode root;

        public Trie()
        {
            root = new TrieNode();
        }

        public void insert(String word)
        {
            TrieNode head = root;
            head.path++;
            for (char ch : word.toCharArray())
            {
                int idx = ch - 'a';
                if (head.map[idx] == null)
                    head.map[idx] = new TrieNode();
                head = head.map[idx];
                head.path++;
            }
            head.end++;
        }

        public boolean search(String word)
        {
            TrieNode head = root;
            for (char ch : word.toCharArray())
            {
                if (head.map[ch - 'a'] != null)
                    head = head.map[ch - 'a'];
                else return false;
            }
            return head.end != 0;
        }

        public void delete(String word)
        {
            if (!search(word)) return;
            TrieNode head = root;
            head.path--;
            for (char ch : word.toCharArray())
            {
                if (--head.map[ch - 'a'].path == 0)
                {
                    head.map[ch - 'a'] = null;
                    return;
                }
                head = head.map[ch - 'a'];
            }
            head.end--;
        }

        public int prefixNumber(String pre)
        {
            TrieNode head = root;
            for (char ch : pre.toCharArray())
            {
                head = head.map[ch - 'a'];
                if (head == null) return 0;
            }
            return head.path;
        }
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        Trie trie = new Trie();
        int n = Integer.parseInt(in.nextLine());
        while (n-- > 0)
        {
            String[] input = in.nextLine().split(" ");
            int op = Integer.parseInt(input[0]);
            String word = input[1];
            switch (op)
            {
                case 1:
                    trie.insert(word);
                    break;
                case 2:
                    trie.delete(word);
                    break;
                case 3:
                    System.out.println(trie.search(word) ? "YES" : "NO");
                    break;
                case 4:
                    System.out.println(trie.prefixNumber(word));
                    break;
            }
        }
    }
}

CD141 子数组的最大异或和⭐

/* 超时 */
public class CD141_1
{

    public static int solution(int[] arr)
    {
        int[] xor = new int[arr.length];
        int ans = Integer.MIN_VALUE;
        xor[0] = arr[0];
        for (int i = 1; i < arr.length; i++)
            xor[i] = xor[i - 1] ^ arr[i];
        for (int i = 0; i < xor.length; i++)
            for (int j = 0; j < i; j++)
                ans = Math.max(ans, xor[i] ^ xor[j]);
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr));
    }
}

/* ⭐前缀树⭐ */
public class CD141_2
{
    public static class TrieNode
    {
        public TrieNode[] map;

        public TrieNode()
        {
            map = new TrieNode[2];
        }
    }

    public static class Trie
    {
        private TrieNode root;

        public Trie()
        {
            root = new TrieNode();
        }

        public void add(int num)
        {
            TrieNode head = root;
            for (int i = 31; i >= 0; i--)
            {
                int idx = (num >> i) & 1;
                if (head.map[idx] == null)
                    head.map[idx] = new TrieNode();
                head = head.map[idx];
            }
        }

        public int maxXor(int num)
        {
            TrieNode head = root;
            int res = 0;
            for (int i = 31; i >= 0; i--)
            {
                int t = (num >> i) & 1;
                int idx = i == 31 ? t : t ^ 1;
                idx = head.map[idx] == null ? 1 ^ idx : idx;
                res |= (idx ^ t) << i;
                head = head.map[idx];
            }
            return res;
        }

    }

    public static int solution(int[] arr)
    {
        Trie trie = new Trie();
        int xor = 0, ans = Integer.MIN_VALUE;
        trie.add(0);
        for (int i = 0; i < arr.length; i++)
        {
            xor ^= arr[i];
            ans = Math.max(ans, trie.maxXor(xor));
            trie.add(xor);
        }
        return ans;
    }

    public static void main(String[] args)
    {
        Scanner in = new Scanner(System.in);
        int n;
        n = in.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++)
            arr[i] = in.nextInt();
        System.out.println(solution(arr));
    }
}
posted @ 2023-11-20 13:33  Vivid-BinGo  阅读(10)  评论(0编辑  收藏  举报