程序猿圈子里正在流行一种很新的简写方法:对于一个字符串,只保留首尾字符,将首尾字符之间的所有字符用这部分的长度代替。例如internation-alization 简写成i18n,Kubernetes (注意连字符不是字符电的一部分)简写成 K8s, Langiao 简写成 L5o 等
在本题中,我们规定长度大于等于K 的字符串都可以采用这种简写方法(长度小于K 的字符串不配使用这种简写。
给定一个字符串 S 和两个字符 c1和c2,请你计算 S 有多少个以从c1 开头 c2结尾的子可以采用这种简写?
暴力法
cpp
#include <iostream>
using namespace std;
#define INF 0x3f3f3f3f
int clean(string s, char c1, char c2)
{
int k;
cin >> k;
int count = 0;
if (s.length() < k)return 0; //若字符串小于直接返回0
for (int i = 0; i < s.length(); i++)
{
if(s[i] != c1)continue; //找到第一个c1开头的字符串
for (int j = i; j < s.length(); j++)
{
if (s[j] == s[i]&&(j-i+1)>=k)count++;
}
}
return count;
}
signed main()
{
ios::sync_with_stdio;
cin.tie(0);
cout.tie(0);
string s;
char c1, c2;
int n = 1;
cin >> s;
cin >> c1 >> c2;
while (n--)
cout << clean(s,c1,c2);
}
二分法
cpp
#include <iostream>
using namespace std;
#define INF 0x3f3f3f3f
#include <vector>
int clean(string s, char c1, char c2)
{
int k;
cin >> k;
int count = 0;
if (s.length() < k)return 0; //若字符串小于直接返回0
vector<int>arr;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == c1)
arr.push_back(i);
if (s[i] == c2)
{
if (!arr.size() || (i - k + 1) < 0) //没有一个首字符了,或者第一个尾字符的位置不满足k
continue;
if (arr[0] > (i - k + 1))continue; //判断一种特殊情况所有的都在右边
int l = 0, r = arr.size();
while (l < r)
{
int mid = (l + r + 1) >> 1;
if (arr[mid] > i - k + 1)
r = mid - 1;
else
l = mid;
}
count += l;
}
}
return count;
}
signed main()
{
ios::sync_with_stdio;
cin.tie(0);
cout.tie(0);
string s;
char c1, c2;
int n = 1;
cin >> s;
cin >> c1 >> c2;
while (n--)
cout << clean(s,c1,c2);
}