弱爆了,细节处理不了,代码熟练度也不行,想法有时候还过于复杂,整个人都需要被优化。
A简单题
没有什么算法,字符串代码题。
但是复习了不少关于字符串处理的知识。
题意:给你两个串,一个模式串A,一个匹配串B,找B是否在A里。
模式串A比较特殊acb[3]d[5]e,是被压缩后的数字代表的是压缩的个数。
例:acb[3]d[5]e acbbbddddde(比较坑的点在于他可能不是完全压缩的,在处理的时候还要再压缩一次)
这是学长给我指出来的,善良的孩子总是被恶意欺骗
输入:acb[3]d[5]e
bd
输出:True(没有是False)
想法:把一个串完全压缩,第二串也完全压缩,比较的时候按照字符串匹配(BF)查找即可,当然也可以用(KMP),这里要注意的是,除了要匹配字符串,还要比较数目的大小,要保证B串压缩的数要小于等于A串同一个数。
我的错误的代码(以后注意每一步,都要把运行的结果很好的输出来,以便差错):
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define maxn 1003
struct tt
{
char c;
int n;
};
int main()
{
// char tt[maxn];///临时串
char t[maxn];
char ss[maxn];///输入的临时串
char ns[maxn];///用来被比较的串
tt s[maxn],n_s[maxn];///用来处理分析的串
while(~scanf("%s",ss))
{
scanf("%s",ns);
int count=-1;///第一个模式串的计数器
int len_ss=strlen(ss);///模式串的长度
int len_ns=strlen(ns);///匹配串的长度
for(int i=0;i<len_ss;i++)
{
if(ss[i]>='a'&&ss[i]<='z'){
s[++count].c=ss[i];///处理第一个串
s[count].n=1;
}
if(ss[i]=='[')///统计数,超过1位的整数
{
int sum=0;
int j=0;
int k=i;
i++;
while(ss[i]!=']')
{
t[j++]=ss[i];
i++;
}
sscanf(t,"%d",&sum);
s[count].n=sum;
// cout<<sum<<"*"<<endl;
}
}
int len_1=count+1;
count=-1;
// cout<<ns<<endl;
int cnt=1;
for(int i=0;i<len_ns;i++)
{///匹配串的长度
if(ns[i]!=ns[i+1]){
n_s[++count].c=ns[i];
n_s[count].n=cnt;
cnt=1;
}
else cnt++;
}
int len_2=count+1;
/* for(int i=0;i<len_1;i++)///输出的测试表
cout<<s[i].c<<" "<<s[i].n<<endl;
for(int i=0;i<len_2;i++)
cout<<n_s[i].c<<" "<<n_s[i].n<<endl;*/
int i=0,j=0,flag=0;
while(i<len_1&&j<len_2)///串的匹配
{
if(s[i].c==n_s[j].c&&s[i].n>=n_s[j].n)
{
cout<<s[i].c<<" "<<n_s[j].c<<endl;
i++;
j++;
}
else{
i=i-j+1;
j=0;
}
if(j>=len_2)
flag=1;
}
if(flag==1)///输出结果
cout<<"True"<<endl;
else
cout<<"False"<<endl;
// cout<<count+1<<endl;
// ss[count++]='\0';
}
return 0;
}
正确的代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
#include <cmath>
#include <iomanip>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
#define rd3(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
ll has1[1011];
ll has11[1011];
ll has2[1011];
string s1;
string s2;
string s11;
string tp;
string tp2;
void change()
{
//瘦身s1
int len1=tp2.length();
s1="";
int pos=0;
for(int i=0;i<len1;i++)
{
ll num=1;
if(isalpha(tp2[i]))
{
s1.push_back(tp2[i]);
if(i+1<len1&&tp2[i+1]=='[')//左括号的位置
{
num=0;
int r=i+2;
while(tp2[r]!=']')
{
num=num*10+tp2[r]-'0';
r++;
}
i=r;
}
has1[pos++]=num;
}
}
//s1去重,比如aacccdfe这种的
pos=0;
s11="";
len1=s1.length();
for(int i=0;i<len1;i++)
{
int r=i+1;
ll cnt=has1[i];
s11.push_back(s1[i]);
while(s1[r]==s1[i])
{
cnt+=has1[r];
r++;
}
has11[pos++]=cnt;
if(r==i+1)
continue;
i=r-1;
}
int len=tp.length();
s2="";
pos=0;
for(int i=0;i<len;i++)
{
int cnt=1;
for(int p=i+1;p<len;p++)
{
if(tp[p]==tp[p-1])
cnt++;
else
break;
}
if(cnt==1)
{
s2.push_back(tp[i]);
// pos++;
has2[pos++]=1;
}
else
{
s2.push_back(tp[i]);
has2[pos++]=cnt;
i=i+cnt-1;
}
}
}
bool work()
{
int len1=s11.length();
int len2=s2.length();
/*
cout<<"s11 "<<s11<<endl;
for(int i=0;i<s11.length();i++)
cout<<has11[i]<<" ";
cout<<endl;
cout<<"s22 "<<s2<<endl;
for(int i=0;i<s2.length();i++)
cout<<has2[i]<<" ";
cout<<endl;*/
for(int i=0;i<len1;i++)
{
int p1=i;
int p2=0;
if(s11[p1]!=s2[p2])
continue;
//首先第一个字母
if(has11[p1]<has2[p2])
continue;
if(has11[p1+len2-1]<has2[len2-1])
continue;
if(len2==1||len2==2)
return true;
p1++;
p2++;
while(p2<len2-1)
{
if(s11[p1]!=s2[p2])
break;
if(has11[p1]!=has2[p2])
break;
p1++;
p2++;
}
if(p2==len2-1)
return true;
}
return false;
}
int main()
{
while(cin>>tp2>>tp)
{
memset(has1,0,sizeof(has1));
memset(has2,0,sizeof(has2));
memset(has11,0,sizeof(has11));
change();
if(work())
printf("True\n");
else
printf("False\n");
}
return 0;
}
唉,就是跟我这种小菜鸟的感觉,不一样。
B、逆序数还原
应该被秒A的题,我还是做了很长时间。还因为没有换行而导致PE了一次。
题意:给出N,表示数组的个数,再给出一个状态数组,该数组表示该数后面有几个比他小的数。
让你还原数组,输出。
例:2 0 1 0 0
3 1 4 2 5
注意的是题目中没有明确指明,数一定是从1到n的。
输入:5
2 0 1 0 0
输出:3 1 4 2 5
想法:在未选择的序列排的序号就是给出的状态号。比如假设1 2 3 4 5,如果排序为3 1 4 2 5,那么比3小得一定有两个,到1的时候,如果说状态号为0的号,即是排第一的数,当然之前选择过得数要被摘出去。
代码:
#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 1002
int t[maxn],now[maxn];
int main()
{
int n,tt;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)///初始化,全部为1标记
t[i]=1;
for(int i=0;i<n;i++)
{
int count=-1;
scanf("%d",&tt);///tt表示后面有几个比他大的数
for(int j=0;j<n;j++)
{
if(t[j]==1)
count++;
if(count==tt)
{
now[i]=j+1;
t[j]=0;
break;
}
}
}
printf("%d",now[0]);
for(int i=1;i<n;i++)
printf(" %d",now[i]);
printf("\n");
}
return 0;
}
后面都没做出来,因为有些事没能坚持做到最后。。。。。。
3、数的路径覆盖
4、小明的迷宫
刚看到这道题的时候,想到是搜索,但是同学说会超时,要用状态压缩dp,已经完全忘记了有没有
5、回家种地
6、迷宫I
7、迷宫II
坐等各位大神的题解出来然后我再来补充不懂知识点啊