1
输入:第一行为操作总数Q,之后有Q行。每行一个操作。
操作1,将字符串加在原字符串末尾。
操作2,给定长度,从字符串末尾删除。
操作3,查询现在字符串中第k个字符。
操作4,回滚一次操作(只回滚增删操作)。
难度:easy
耗时:10min
public class Main {
static StringBuilder sb = new StringBuilder();
static Stack<String> st = new Stack();
private static void add(String s) {
st.push(sb.toString());
sb.append(s);
}
private static char search(int pos) {
return sb.charAt(pos-1);
}
private static void delete(int len) {
st.push(sb.toString());
sb.setLength(sb.length() - len);
}
private static void rollback() {
sb = new StringBuilder(st.pop());
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int Q = sc.nextInt();
sc.nextLine();
for (int j = 0; j < Q; j++) {
String[] arr = sc.nextLine().split("\\s+");
if (arr[0].equals("1"))
add(arr[1]);
else if (arr[0].equals("2"))
delete(Integer.parseInt(arr[1]));
else if (arr[0].equals("3")) {
char c = search(Integer.parseInt(arr[1]));
System.out.println(c);
} else
rollback();
}
}
}
2
输入:第一行为需要翻译的文本M。len(M) <= 50000.
第二行为字典中单词数n。2 <= n <= 50000.
每一个单词长度不超过20。
之后有n行,每一行代表一个单词。
返回总共有多少种翻译文本的方式。
返回的结果需要%835672545。
样例:
abcba
5
a
ab
ba
bc
cb
// 输出2
ab | cb | a
a | bc | ba
难度:medium
耗时:50min
一开始没有降维,MLE。
public class Main {
static final int kMod = 835672545;
private static int search(HashSet<String> dict, String s) {
int n = s.length();
int[][] dp = new int[n+1][n+1];
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++) {
String tmp = s.substring(i-1, j);
if (dict.contains(tmp))
dp[i][j] = 1;
}
for (int len = 1; len <= n; len++) {
for (int i = 1; i+len-1 <= n; i++) {
int j = i + len - 1;
for (int k = i; k < j; k++) {
String s2 = s.substring(k, j);
if (dp[i][k] > 0 && dict.contains(s2)) {
dp[i][j] = (dp[i][j] + dp[i][k]) % kMod;
}
}
}
}
// System.out.println(dp[1][1]); //a
// System.out.println(dp[1][2]); // ab
// System.out.println(dp[1][3]); // a | bc
// System.out.println(dp[1][4]); // ab | cb
return dp[1][n];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String target = sc.nextLine();
int Q = sc.nextInt();
sc.nextLine();
HashSet<String> dict = new HashSet();
for (int j = 0; j < Q; j++) {
dict.add(sc.nextLine());
}
System.out.println(search(dict, target));
}
}
第二次,没有用Math.max优化长度,TLE。而且显示test case通过率为0,特别慌。
第三次终于AC。
public class Main {
static final int kMod = 835672545;
private static int search(HashSet<String> dict, String s) {
int n = s.length();
int[] dp = new int[n+1];
dp[0] = 1;
for (int r = 1; r <= n; r++) {
for (int l = Math.max(1, r-20); l <= r; l++) {
String tmp = s.substring(l-1, r);
if (dp[l-1] > 0 && dict.contains(tmp))
dp[r] = (dp[r] + dp[l-1]) % kMod;
}
}
return dp[n];
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String target = sc.nextLine();
int Q = sc.nextInt();
sc.nextLine();
HashSet<String> dict = new HashSet();
for (int j = 0; j < Q; j++) {
dict.add(sc.nextLine());
}
System.out.println(search(dict, target));
}
}
3
输入:第一行两个整形,m表示天数,n表示袜子数量(只)。
第二行是每只袜子的颜色(用整形表示)。
之后有m行,每一天穿两只固定序号的袜子。但是必须保证两只袜子颜色一样。如果不一样,需要涂改袜子的颜色使这两只袜子的颜色能够匹配。代价为1。
返回最小代价。
难度:medium - hard
耗时:10min
应该是个dp问题。但是我连暴力解都没写出来。下面是个错误解法。
public class Main {
static int[] color;
static int[] color2;
static int[][] comb;
static int m;// number of days
static int n;// number of socks
private static int paint() {
// dp[i][j][k] := min number of painting
// in day i, painting j-th sock to color k
// int[][][] dp = new int[m+1][n][n];
// dp[0] = color.clone();
int cnt = 0;
for (int i = 0; i < m; i++) {
int sock1 = comb[i][0];
int sock2 = comb[i][1];
boolean same1 = true;
boolean same2 = true;
if (color[sock1] != color[sock2]) {
color[sock1] = color[sock2];
same1 = false;
}
if (color2[sock1] != color2[sock2]) {
color2[sock2] = color2[sock1];
same2 = false;
}
if (!same1 && !same2)
cnt++;
}
return cnt;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
m = sc.nextInt();
color = new int[n+1];
comb = new int[m][2];
for (int i = 1; i <= n; i++) {
int c = sc.nextInt();
color[i] = c;
}
color2 = color.clone();
sc.nextLine();
for (int j = 0; j < m; j++) {
String[] arr = sc.nextLine().split("\\s");
comb[j][0] = Integer.parseInt(arr[0]);
comb[j][1] = Integer.parseInt(arr[1]);
}
System.out.println(paint());
}
}
4
对给定字符串有两种操作。
操作1,修改第k个字符为新字符c。
操作2,查询给定范围内不同字符的个数。
难度:hard
耗时:10min
没写出来,只写了一个暴力解,60%测试用例超时。
我估计使用Trie。
public class Main {
static StringBuilder sb = null;
private static int query(int l, int r) {
HashSet<Character> cnt = new HashSet();
for (int i = l-1; i < r; i++) {
cnt.add(sb.charAt(i));
}
return cnt.size();
}
private static void update(int pos, String s) {
sb.setCharAt(pos-1, s.charAt(0));
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String target = sc.nextLine();
sb = new StringBuilder(target);
int Q = sc.nextInt();
sc.nextLine();
HashSet<String> dict = new HashSet();
for (int j = 0; j < Q; j++) {
String[] arr = sc.nextLine().split("\\s");
if (arr[0].equals("2")) { // query
System.out.println(query(Integer.parseInt(arr[1]), Integer.parseInt(arr[2])));
} else {
update(Integer.parseInt(arr[1]), arr[2]);
}
}
}
}
做完心态是崩溃的。