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));
}
}