1009 Command Sequence
Problem Description
There is a robot that can move by receiving a sequence of commands.
There are four types of command in the command sequence:
U: robot moves one unit up.
D: robot moves one unit down.
L: robot moves one unit left.
R: robot moves one unit right.
Now, given a command sequence of length n. You need to find out how many substrings of the command sequence satisfy that if the robot execute the substring command, it can return to the starting position.
A substring is a contiguous sequence of characters within a string. For instance, “the best of” is a substring of “It was the best of times”. For example, “Itwastimes” is a subsequence of “It was the best of times”, but not a substring.
Input
This problem contains multiple test cases.
The first line contains an integer t (1≤t≤20) indicating the number of test cases.
For each test case, the first line contains one integer n (2≤n≤10^5).
The second line contains a UDLR string of length n.
Output
For each test case, output one line one integer indicating the answer.
Sample Input
1
6
URLLDR
Sample Output
2
题目大意:
一个机器人可以执行上下左右(UDLR)四个命令,执行每个命令时移动一个单位距离。
给定一条由UDLR组成的命令字符串,问有多少个子串满足当机器人执行完这个子串命令后可以回到起点。
例如UUDDUDLRRR的子串UD可以满足要求。
题解:
如果采用暴力的方法枚举每一个子串,那么一定会超时。
我们遍历整条命令,并记录执行完每一个命令的位置(x, y)。
如果有一个子串可以使机器人回到原点,那么执行子串前和执行子串后的位置(x, y)应该是相同的。
所以当我们执行完某个命令后,只需要判断当前位置(x, y)在之前有没有出现过,即可判断终点为当前位置的满足要求的子串数量。
例如如果当前位置(x, y)在之前出现过2次,说明有2个终点为当前位置的子串满足要求。
枚举所有终点不断累加当前(x, y)在之前出现过的次数即可得到答案。
我们可以用map<pair<int, int>, int>来记录每一个坐标出现的次数,到一个位置就记录当前位置map[{x, y}] ++,并不断累加前位置(x, y)在前面出现的次数res += map[{x, y}]。
注意起点(0, 0)不要忘了记录。
AC代码:
#include <iostream>
#include <map>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PAIR;
int main() {
ios::sync_with_stdio(false);
ll t;
cin >> t;
while (t --) {
map<PAIR, ll> mp;
mp[{0, 0}] ++; // 起点(0, 0)也要记录
ll n;
string s;
cin >> n >> s;
ll res = 0, x = 0, y = 0; // 初始化坐标为(0, 0)
for (ll i = 0; i < s.length(); i ++) { // 遍历整条命令
if (s[i] == 'U') x ++;
else if (s[i] == 'D') x --;
else if (s[i] == 'L') y ++;
else if (s[i] == 'R') y --;
res += mp[{x, y}]; // 累加当前位置(x, y)在前面出现的次数
mp[{x, y}] ++; // 记录当前位置
}
cout << res << '\n';
}
return 0;
}