D. Remove Two Letters
D. Remove Two Letters
Dmitry has a string , consisting of lowercase Latin letters.
Dmitry decided to remove two consecutive characters from the string and you are wondering how many different strings can be obtained after such an operation.
For example, Dmitry has a string "aaabcc". You can get the following different strings: "abcc"(by deleting the first two or second and third characters), "aacc"(by deleting the third and fourth characters),"aaac"(by deleting the fourth and the fifth character) and "aaab" (by deleting the last two).
Input
The first line of input data contains a single integer () — number of test cases.
The descriptions of the test cases follow.
The first line of the description of each test case contains an integer ().
The second line of the description of each test case contains a string of length consisting of lowercase Latin letters.
It is guaranteed that the sum of for all test cases does not exceed .
Output
For each test case print one integer — the number of distinct strings that can be obtained by removing two consecutive letters.
Example
input
7 6 aaabcc 10 aaaaaaaaaa 6 abcdef 7 abacaba 6 cccfff 4 abba 5 ababa
output
4 1 5 3 3 3 1
Note
The first example is explained in the statement.
In the third example, the following strings are obtained: "cdef", "adef", "abef", "abcf", "abcd".
In the seventh example, any deletion will result in the string "aba".
解题思路
一开始想到字符串哈希,结果人品不好被hack了。取被下面的数据hack了,正确答案应该是,而得到的答案是。
1 18 aaibfprdokxvipsqaa
但有意思的是就可以AC了,真就玄学。
比如如果要把和删除,然后将和这两部分拼接,那么拼接后的字符串对应的哈希值就是。然后把个拼接字符串的哈希值加到哈希表中,最后答案就是哈希表的大小。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef unsigned long long ULL; 5 6 const int N = 2e5 + 10, P = 13331; 7 8 char s[N]; 9 ULL h[N], p[N]; 10 11 ULL get(int l, int r) { 12 if (l > r) return 0; 13 return h[r] - h[l - 1] * p[r - l + 1]; 14 } 15 16 void solve() { 17 int n; 18 scanf("%d %s", &n, s + 1); 19 p[0] = 1; 20 for (int i = 1; i <= n; i++) { 21 p[i] = p[i - 1] * P; 22 h[i] = h[i - 1] * P + s[i]; 23 } 24 unordered_set<ULL> st; 25 for (int i = 1; i < n; i++) { 26 st.insert(get(1, i - 1) * p[n - i - 1] + get(i + 2, n)); 27 } 28 printf("%d\n", st.size()); 29 } 30 31 int main() { 32 int t; 33 scanf("%d", &t); 34 while (t--) { 35 solve(); 36 } 37 38 return 0; 39 }
给出正解。
考虑删除和,和和后所得到的两个字符串,前一个字符串会保留和,后一个字符串会保留和,可以发现小于的位置和超过的位置都是一样的。因此如果前一个字符串的和后一个字符串的相同,那么这两个字符串就是相同的。
因此对于,比较和,如果相同则存在一个字符串是重复的。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 2e5 + 10; 5 6 char s[N]; 7 8 void solve() { 9 int n; 10 scanf("%d %s", &n, s + 1); 11 int ret = n - 1; 12 for (int i = 1; i < n; i++) { 13 if (s[i] == s[i + 2]) ret--; 14 } 15 printf("%d\n", ret); 16 } 17 18 int main() { 19 int t; 20 scanf("%d", &t); 21 while (t--) { 22 solve(); 23 } 24 25 return 0; 26 }
参考资料
Codeforces Round 855 (Div. 3) Editorial:https://codeforces.com/blog/entry/113477
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17178255.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效