弱爆了,細節處理不了,代碼熟練度也不行,想法有時候還過於複雜,整個人都需要被優化。
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
坐等各位大神的題解出來然後我再來補充不懂知識點啊