B. 宿舍战争
它找到所有位置 i (1≤i<m) 使得 si+1 是 k 个特殊字母之一。
然后它会从密码 s 中删除所有这些位置,即使 si 是一个特殊字符。如果没有要删除的位置,则程序会显示一条声音很大的错误消息。
例如,假设字符串 s 是“abcdef”,特殊字符是“b”和“d”。如果他运行一次程序,位置 1 和 3 将被删除,因为它们位于特殊字符之前,因此密码变为“bdef”。如果他再次运行程序,它会删除位置 1,密码变为“def”。如果他是明智的,他不会运行它第三次。
Hosssam 想知道他可以在 Hemose 的笔记本电脑上运行该程序多少次,而不会被错误消息的声音吵醒。你能帮助他吗?
输入
第一行包含一个整数 t (1≤t≤105)——测试用例的数量。然后是 t 个测试用例。
每个测试用例的第一行包含一个整数 n (2≤n≤105) — 密码的初始长度。
下一行包含一个由 n 个小写英文字母组成的字符串 s — 初始密码。
下一行包含一个整数 k (1≤k≤26),后跟 k 个不同的小写字母 c1,c2,...,ck — 特殊字母。
保证所有测试用例的 n 之和不超过 2⋅105。
输出
对于每个测试用例,在新行上打印 Hossam 可以在不显示错误消息的情况下运行程序的最大次数。
Example
input
10 9 iloveslim 1 s 7 joobeel 2 o e 7 basiozi 2 s i 6 khater 1 r 7 abobeih 6 a b e h i o 5 zondl 5 a b c e f 6 shoman 2 a h 7 shetwey 2 h y 5 samez 1 m 6 mouraz 1 moutput
5 2 3 5 1 0 3 5 2 0
解决方法:
1.我们只要找到两个特殊字符的最大距离即可
2.用l记录前一个特殊字符的位置,用r记录后一个特殊字符的位置
/*
只需求两个字符间的最大距离
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
void solve()
{
int n, m;
string s;
cin >> n;
cin >> s;
map<char, int>mp;
cin >> m;
for(int i=0; i<m; i++)
{
char a;
cin >> a;
mp[a] ++;
}
int l = 0, r = 0; //统计两个特殊字符的前后位置
int ans = 0; //寻找最大的位置
for(int i=0; i<n; i++)
{
if(mp[s[i]])
{
l = r;
r = i;
ans = max(ans, r - l);
}
}
cout << ans << endl;
}
int main()
{
int T;
cin >> T;
while(T --)
{
solve();
}
return 0;
}