目录
字符串模拟
1. 东东哥的等式(简单模拟)
例题1:东东哥的等式
东东哥又在玩字符串啦,他有一个长度为n的十进制串(n<=36),他想在这个串里插入一个’+‘和一个’=’(’+‘必须在’='前面),使其变为x+y=z的形式,x,y,z为十进制数并且不允许包含前导0.请输出这个式子,如果有多个请输出x最小的那个。保证至少存在一个答案而且仅存在一个满足x最小的答案。东东哥实在想不出来怎么做这题,你能帮帮他吗?
思路:简单的字符串模拟,注意用char数组,用string会数组越界。分别截取转换成数字,符合要求即输出,要特判保证没有前导零
#include<bits/stdc++.h>
using namespace std;
int t,n,m;
char s[105];
typedef unsigned long long ll;
ll stoi(char *ss,ll l,ll r)//自己写一个字符串转整数。想知道为什么cstring里包含的stoi()用不了
{
ll res=0;
if(l>r)return 0;
for (ll i=l;i<=r;i++)
{
res*=10;
res+=ss[i]-'0';
}
return res;
}
bool valid(char *c,ll l,ll r)
{
if(l!=r&&c[l]=='0')return false;
return true;
}
int main()
{
cin>>t;
while(t--)
{
scanf("%s",s);
int len=strlen(s);
for(int i=0;i<=len/2+1;i++)
{
for(int j=i+1;j<=len-1;j++)
{
if(!valid(s,0,i)||!valid(s,i+1,j)||!valid(s,j+1,len-1))continue;
ll le=stoi(s,0,i);
ll mid=stoi(s,i+1,j);
ll ri=stoi(s,j+1,len-1);
if(le+mid==ri)//if(le+mid==ri&&(s[i+1]!='0'||i+1==j)&&(s[j+1]!='0'||j+1==strlen(s)-1))
{
cout<<le<<"+"<<mid<<"="<<ri<<endl;
goto flag;
}
}
}
flag:;
}
return 0;
}
2.有几个zucc(字符数,简单排列组合)
例题2:有几个zucc
字符串 AAZBCZCUCIOCQWC 共包含6个 ZUCC。
例如,第3位(Z),第8位(U),第9位©,第12位©可以形成一个ZUCC;
第6位(Z),第8位(U),第12位©,第15位©也可以形成一个 ZUCC。
下面给定一个长度不超过 100000且仅包含大写 A-Z 字母的字符串。一共可以形成多少个 ZUCC?
输入格式:
输入只有一行,包含一个长度不超过 100000。
输出格式:
输出该字符串中包含的 ZUCC 个数。
输入样例:
AAZBCZCUCIOCQWC
输出样例:
6
思路:从后往查,n个C,两个一组,n*(n-1)/2种。只要有U,每多一个Z,多一倍。
#include<stdio.h>
#include<string.h>
char s[100001];
int main()
{
int c=0;
int len=0;
long long usum=0;
long long sum=0;
scanf("%s",s);
len=strlen(s);
for(int i=len-1;i>=0;i--){
if(s[i]=='C') c++;
else if(s[i]=='U') usum+=c*(c-1)/2;
else if(s[i]=='Z') sum+=usum;
}
printf("%lld\n",sum);
return 0;
}
3.拼数(简单字符串,小技巧)
3.拼数
设有n个正整数(n≤20),将它们联接成一排,组成一个最大的多位整数。
思路:利用c++中字符串string的性质排序即可
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
int n;
string s[maxn];
bool cmp(string a,string b)
{
return a+b>b+a; //直接按字典序排序先拼接到一块看那个大
}
int main()
{
cin>>n;//利用字符串可以更加简便
for(int i=0;i<n;i++)
cin>>s[i];
sort(s,s+n,cmp);
for(int i=0;i<n;i++)
cout<<s[i];
cout<<endl;
return 0;
}
4.CF1295B 【Infinite Prefixes】(字符串,前缀和,数论)
题目表达的很难看懂,简单来说就是给一个长度已知可以无限重复的字符串,只有0和1两种字符,问有几个点可以使0比1多x个,比如样例1, 010010 1个子串0比1多2个,所以前四个子串结束后0一共比1多了8个,而0比1多10个将在下一个子串中出现,也就是第28 30 和32位的时候。
用一个前缀和pre[N]数组来表示当前0和1的个数差值,然后特判即可。具体的直接看代码。
#include<bits/stdc++.h>
#define debug cout<<"ok"<<endl
using namespace std;
typedef long long ll;
const int N=1e5+7;
const int mod=1e9+7;
ll n,x,t,pre[N];
string s;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>t;
while(t--)
{
cin>>n>>x>>s;
ll ans=0;bool flag=0;pre[0]=0;
for(int i=0;i<s.length();i++)
{
if(s[i]=='0')pre[i+1]=pre[i]+1;//前缀和数组,pre[i]表示0的个数与1的个数的差值
else pre[i+1]=pre[i]-1;
}
ll date=pre[s.length()];
for(int i=0;i<=s.length();i++)//要<=因为看走完如果是否满足题意
{
if(pre[i]==x)ans++;
if(pre[i]==x&&date==0)flag=1;
if(i!=0&&pre[i]<x&&date>0&&(x-pre[i])%date==0)ans++;/*走到这儿是1多,但是走完一遍是0多,那么如果x-pre[i]%date==0那么往后延伸一定能出现0比1多x的情况,所以ans++;*/
if(i!=0&&pre[i]>x&&date<0&&(pre[i]-x)%(-date)==0)ans++;
}
if(!flag)
cout<<ans<<endl;
else cout<<-1<<endl;
}
return 0;
}
5.CF1295C - Obtain The String(模拟取字符串子序列)
题目大意:
给定两个字符串s和t,你有一个空字符串z
每次可以取s的任意一个子序列加到z后面
问至少要取多少次才能让z等价于t
题解
6.nozomi和字符串 (字符串,滑动窗口,贪心)
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int a[N];
string s;
int n,m;
int main()
{
cin>>n>>m;
cin>>s;
queue<int>q1;
queue<int>q2;
q1.push(-1);
q2.push(-1);
int maxxx=0,maxn=0,ans=0;
for(int i=0;i<n;i++)
{
if(s[i]=='0')
q1.push(i);
if(q1.size()>m+1)
q1.pop();
int temp=i-q1.front();
if(temp>maxn)
maxn=temp;
if(s[i]=='1')
q2.push(i);
if(q2.size()>m+1)
q2.pop();
int t=i-q2.front();
if(t>maxxx)
maxxx=t;
ans=max(maxxx,maxn);
}
cout<<ans<<endl;
}
7.潜伏者(字符串,密码解密)
加密问题
潜伏者
题目描述
RR R国和S S S国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动。历尽艰险后,潜伏于S S S国的R RR 国间谍小C C C终于摸清了 SSS 国军用密码的编码规则:1. SS S国军方内部欲发送的原信息经过加密后在网络上发送,原信息的内容与加密后所得的内容均由大写字母‘AAA’-‘ZZZ’构成(无空格等其他字符)。2. SS S国对于每个字母规定了对应的“密字”。加密的过程就是将原信息中的所有字母替换为其对应的“密字”。3. 每个字母只对应一个唯一的“密字”,不同的字母对应不同的“密字”。“密字”可以和原字母相同。例如,若规定‘AAA’的密字为‘AAA’,‘BBB’的密字为‘CCC’(其他字母及密字略),则原信息“ABAABAABA”被加密为“ACAACAACA”。现在,小C CC 通过内线掌握了S SS 国网络上发送的一条加密信息及其对应的原信息。小C CC希望能通过这条信息,破译S SS 国的军用密码。小 CCC 的破译过程是这样的:扫描原信息,对于原信息中的字母x xx(代表任一大写字母),找到其在加密信息中的对应大写字母y yy,并认为在密码里 yy y是x x x的密字。如此进行下去直到停止于如下的某个状态:1. 所有信息扫描完毕,‘AAA’-‘ZZZ’ 所有 2626 26个字母在原信息中均出现过并获得了相应的“密字”。2. 所有信息扫描完毕,但发现存在某个(或某些)字母在原信息中没有出现。3. 扫描中发现掌握的信息里有明显的自相矛盾或错误(违反 SSS 国密码的编码规则)。例如某条信息“XYZXYZXYZ”被翻译为“ABAABAABA”就违反了“不同字母对应不同密字”的规则。在小 CCC 忙得头昏脑涨之际,RRR 国司令部又发来电报,要求他翻译另外一条从 SS S国刚刚截取到的加密信息。现在请你帮助小C CC:通过内线掌握的信息,尝试破译密码。然后利用破译的密码,翻译电报中的加密信息。
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
string s1,s2,s3,s="";
int n,m,cnt,vis[maxn],a[maxn],vis2[maxn];
int main()
{
cin>>s1>>s2>>s3;
memset(vis,-1,sizeof(vis));
memset(vis2,-1,sizeof(vis2));
int len=s1.length();
for(int i=0;i<len;i++)
{
if(vis[s1[i]-'A']==-1&&vis2[s2[i]-'A']==-1)//都没被连过才使它们连接到一块
{vis[s1[i]-'A']=s2[i]-'A';vis2[s2[i]-'A']=0;}
else {
if(vis[s1[i]-'A']!=s2[i]-'A')//要注意这一句要放到里面特判,因为放到外面没办法保证同时满足条件
{cout<<"Failed"<<endl;return 0;}//发现被连过了且想跟它连的是非法的就输出
}
}
for(int i=0;i<26;i++)
if(vis[i]==-1){cout<<"Failed"<<endl;return 0;}
for(int i=0;i<s3.length();i++)
s+=vis[s3[i]-'A']+'A';
cout<<s<<endl;
return 0;
}
/*调之前挂掉的点:QWERTYUIOPLKJHGFDSAZXCVBNM QWERTYUIOPLKJHGFDSAZXCVBNN HIJACK Failed*/
8. CF16A Flag(字符串,getchar()的秒用)
CF16A Flag
题目描述
根据一项新的ISO标准,每一个国家的国旗应该是一个n×m的格子场,其中每个格子最多有10种不同的颜色。并且国旗应该有条纹:旗帜的每一行应包含相同颜色的方块,相邻的行的颜色应该是不同的。Berland政府要求你找出他们的国旗是否符合新的ISO标准。
输入格式:
输入的第一行包含数n和m( ( 1<=n,m<=100 ),其中n为行数,m为列数。接下来
是对旗的描述:以下N行中的每一行包含m个字符。每个字符是0到9之间的数字,代表相应正方形的颜色。
输出格式:
如果国旗符合标准就输出YES,否则输出NO。
注意getchar的使用
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3;
int n,m;
char ch,now,last=' ';
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();//只使用getchar()的话一定要用这句话来接收换行空格等字符;
for(int j=1;j<m;j++)
{
now=getchar();
if(now!=ch){cout<<"NO"<<endl;return 0;}
}
if(last==now){cout<<"NO"<<endl;return 0;}
last=ch;
}
cout<<"YES"<<endl;
return 0;
}
9.nozomi和字符串(字符串,滑动窗口,01子串,0变1/1变0)
nozomi看到eli在字符串的“花园”里迷路了,决定也去研究字符串问题。 她想到了这样一个问题: 对于一个 “01”串而言,每次操作可以把 0 字符改为 1 字符,或者把 1字符改为 0 字符。所谓“01”串,即只含字符 0和字符 1 的字符串。 nozomi有最多k次操作的机会。她想在操作之后找出一个尽可能长的连续子串,这个子串上的所有字符都相同。 nozomi想问问聪明的你,这个子串的长度最大值是多少? 注: k次操作机会可以不全部用完。 如果想知道连续子串的说明,可以去问问eli,nozomi不想再讲一遍。
输入描述:
第一行输入两个正整数 n 和 k 输入仅有一行,为一个长度为 的、仅由字符 0 和 1 组成的字符串。
输出描述:
一个正整数,为满足条件的子串长度最大值。
输入:
5 1
10101
输出:
3
送一个输入:
5 1
00100
输出:
5
思路:贪心的想,显然操作要么全1变0,要么全0变1。用队列维护l
左界,用i代表r
右界,就一滑动窗口,跟单调队列有点像的解法
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int a[N];
string s;
int n,m;
int main()
{
cin>>n>>m;
cin>>s;
queue<int>q1;
queue<int>q2;
q1.push(-1);//要push的是-1而不是0!!因为下面是i-q1.front()而i是从0开始的
q2.push(-1);
int maxxx=0,maxn=0,ans=0;
for(int i=0;i<n;i++)
{
if(s[i]=='0')
q1.push(i);
if(q1.size()>m+1)
q1.pop();
int temp=i-q1.front();
if(temp>maxn)
maxn=temp;
if(s[i]=='1')
q2.push(i);
if(q2.size()>m+1)
q2.pop();
int t=i-q2.front();
if(t>maxxx)
maxxx=t;
ans=max(maxxx,maxn);
}
cout<<ans<<endl;
}
10.丢人!问最少需要几步实现又没非得让你写代码实现!!!
草(一种植物)
题目看起来是编辑距离的模板题,其实就是一个很简单的题目,贪心地考虑问题。先考虑两个字符串相同的部分,显然,只要把原字符串和新字符串不同的字符修改就行了;对于两个字符串后面不同的部分,如果原字符串比较长,就全部删掉;如果原字符串比较短,就对照第二个字符串添加字符。所以,只要按照两个字符串较大的长度进行遍历,比较两个字符串不同的字符有几个就可以了。如果一个字符串比较短,那么它后面的部分可以看成\0
,同样可以参与字符串比较。
这里不能用string因为C++的string类是动态开内存的,当s1,s2长度不一样s[i]就会越界错误
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e6+7;
char s1[N],s2[N];
int main()
{
ll n,sum=0,m;
cin>>n>>m;
scanf("%s%s",s1,s2);
ll len=max(n,m);
for(int i=0;i<len;i++)
{
if(s1[i]!=s2[i])
sum++;
}
cout<<sum<<endl;
return 0;
}