A. Diagonal Walking
简单模拟
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; int n; char s[110]; vector<char> G; int main(){ scanf("%d", &n); scanf("%s", s+1); int i = 1; while(i<=n){ if((s[i] == 'U' && s[i+1] == 'R') || (s[i] == 'R' && s[i+1] == 'U')){ G.push_back('D'); i+=2; } else{ G.push_back(s[i]); i++; } } printf("%d\n", G.size()); return 0; }
B. String Typing(kmp)
题意:有两种操作,往一个字符串末尾添加一个字符,可以操作无限次;将当前字符复制一遍,最多操作一次。现给出一个字符串,问最少操作多少步能够得到该字符串。
题解:首先求出next数组和最小循环节,从后往前找,若某一个前缀出现了多k次该循环节,那么最优的做法一定是先单个添加k/2个循环节,然后复制一遍,然后剩下的再单个添加。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; int n; char s[220]; int nxt[220]; void getnxt(){ nxt[0] = -1; int i = 0, j = -1; while(i<n){ if(j == -1 || s[i] == s[j]){ i++; j++; nxt[i] = j; } else{ j = nxt[j]; } } } int main(){ scanf("%d", &n); scanf("%s", s); getnxt(); int len = 0; int ans = 0; int k = 0; for(int i = n; i>=0; i--){ int t = i-nxt[i]; if(i%t == 0 && i/t>1){ len = t; k = i/t; break; } } if(len!=0){ ans+=len*(k/2); ans++; ans+=len*(k-2*(k/2)); ans+=n-len*k; } else{ ans = n; } printf("%d\n", ans); return 0; }