一、模拟
例题:
卢拉的新语言
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int t,n,a[N];
string s,str;
void solve()
{
memset(a,100,sizeof a);
cin>>n>>s;
str=s;
for(int i=0;i<n;i++)
{
if(s[i]=='a'||s[i]=='e')s[i]='V';
else s[i]='C';
}
string s1;
int k=0;
for(int i=0;i<n;i++)
{
s1+=s[i];
if((s1=="CV"||s1=="CVC")&&(s[i+1]=='C'&&s[i+2]=='V'))a[++k]=i,s1="";
}
for(int i=0,j=1;i<n;i++)
{
cout<<str[i];
if(a[j]==i)
{
cout<<'.';
j++;
}
}
cout<<endl;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>t;
while(t--)solve();
return 0;
}
思路:
1.像这样的字符串遍历问题,因为如‘a’、‘e’ 这一分类有很多对应字母,所以首先应该处理的是将同一个分类里的字母统一,方便判断
2.其次就是对题目的理解和对样例的观察,如何进行“CV”或“CVC”判断,这里用string 特性即可,既然输出‘.’那就要知道在哪里输出‘.’,所以新开一个数组来记录位置,x[j]==i,j++
火车的方向
思路:
string中的find函数,str.find(s,st) s:要在str中找的字符或者字符串 st:在哪里开始找,不写的话,就从第一个字符开始找。如何用?
int len=(int)str.size();
if(str.find(s)<=len)说明在里面
代码
#include<bits/stdc++.h>
using namespace std;
string s,a,b;
bool x,y;
int main()
{
cin>>s>>a>>b;
int n=(int)s.size();
//从b之后的字符串位置开始找 <=字符串长度是判断是否在字符串的一个方法
if(s.find(a)<=n&&s.find(b,s.find(a)+(int)a.size())<=n)
x=true;
reverse(s.begin(),s.end());
if(s.find(a)<=n&&s.find(b,s.find(a)+(int)a.size())<=n)
y=true;
if(x&&y)puts("both");
else if(x&&!y)puts("forward");
else if(!x&&y)puts("backward");
else puts("fantasy");
//find 返回字符串下标 str.find(s,start) 从哪个位置开始查找,不加的话默认从第一个字符开始查找
//找到了返回第一个字符的位置(找字符串也是如此)
//rfind()倒着查找 没有找到返回 string::nops 用s.find(a)==string::npos
return 0;
}
是最小数吗
就是字符串排序,用sort(str.begin(),str.end())
网址合法性
非常恶心的模拟(模拟,就是看自己的代码实现能力能否实现自己脑中所想的东西,还有很多细节自己要想出来)
蓝桥国赛-重复字符串
题意:字串重复k次为k次字符串,是贪心(但我感觉考验模拟,代码能力,所以放在模拟这里)。
思路:首先字符串要能分成k个子串,每个子串的长度即为循环节的长度。不能分的话就输出-1(这里就看字符串的长度能否整除k)例如: 2 aabbaa 这里循环节是 6/2=3 6可整除,所以求更改几个字符。这里每次开始遍历长度为3来遍历循环节,对于每个循环节求其中出现次数最多的字符
代码
//贪心
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int k,n,ans,maxn,cnt[N];
string s;
int main()
{
cin>>k>>s;
n=(int)s.size();
int len=n/k;//循环节长
if(n%k)//能否分出k个循环节
{
cout<<-1<<endl;
return 0;
}
for(int i=0;i<n/k;i++)//按照单个循环节来遍历
{
//
memset(cnt,0,sizeof cnt);
maxn=-1;
//找每个循环节中出现次数最多的字符
for(int j=i;j<n;j+=len)
cnt[s[j]]++;
//求出最多的次数
for(char c='a';c<='z';c++)
maxn=max(maxn,cnt[c]);
//因为要k次重复子串,所以其余字符全部改动
ans+=(k-maxn);
}
cout<<ans;
return 0;
}
牛客循环移位
这种循环移位的见的也多了,应该有点应激反应了,首先将字符串翻倍是必然的,其次什么数是4的倍数,只要这个数字的后两位是4的倍数,那这个数字就是4的倍数。所以,这里的循环移位当然可以用翻倍字符串截取来实现
代码
//1.只看字符串最后两个数字
//2.两倍就是循环了,
#include<bits/stdc++.h>
using namespace std;
string s;
bool check(string w)
{
int x=10*(w[w.size()-2]-'0')+(w[w.size()-1]-'0');
return (x%4==0);
}
int main()
{
cin>>s;
int n=(int)s.size();
string ans=s+s;
for(int i=0;i<n;i++)
{
if(check(ans.substr(i,n)))
{
cout<<i;
return 0;
}
}
cout<<-1;
return 0;
}