数组模拟单链表其实就是链式前向星
只不过是多条链而已
双向链表的话,只需要多做几步即可
注意idx的起点
上一个单链表中起始是0,那么第k个就是k-1
现在idx起始时1,第k个就是k+1
传送门
#include
using namespace std;
const int N=1e5+10;
int l[N],r[N],val[N],idx;
void add(int k,int x){
val[idx]=x;
r[idx]=r[k],l[idx]=k;
l[r[k]]=idx,r[k]=idx++;
}
void remove(int k){
l[r[k]]=l[k];
r[l[k]]=r[k];
}
int main(){
int m;
cin>>m;
l[1]=0;
r[0]=1;
idx=2;
while(m--){
string op;
cin>>op;
int k,x;
if(op=="L"){
scanf("%d",&x);
add(0,x);
}else if(op=="R"){
scanf("%d",&x);
add(l[1],x);
}else if(op=="D"){
scanf("%d",&k);
remove(k+1);
}else if(op=="IL"){
scanf("%d%d",&k,&x);
add(l[k+1],x);
}else {
scanf("%d%d",&k,&x);
add(k+1,x);
}
}
for(int i=r[0];i!=1;i=r[i])cout<
数组模拟栈只需要一个tail变量就可以模拟
传送门
#include
using namespace std;
const int N=1e5+10;
int sta[N],tt;
void push(int x){
sta[++tt]=x;
}
void pop(){
tt--;
}
void ask(){
printf("%d\n",sta[tt]);
}
int main(){
int n;
cin>>n;
for(int i=0;i>op;
if(op=="push"){
scanf("%d",&x);
push(x);
}else if(op=="pop"){
pop();
}else if(op=="empty"){
if(!tt){
printf("YES\n");
}else {
printf("NO\n");
}
}else {
ask();
}
}
return 0;
}
数组模拟队列
也很简单
只需要头指针hh和尾指针tt
注意队列不为空时tt>=hh
传送门
#include
using namespace std;
const int N=1e5+10;
int q[N],tt=-1,hh;
void push(int x){
q[++tt]=x;
}
void pop(){
hh++;
}
int main(){
int n;
cin>>n;
for(int i=0;i>op;
int x;
if(op=="push"){
cin>>x;
push(x);
}else if(op=="pop"){
pop();
}else if(op=="empty"){
if(hh>tt){
printf("YES\n");
}else {
printf("NO\n");
}
}else {
printf("%d\n",q[hh]);
}
}
return 0;
}
单调栈
单调栈就是对于数组每个数,找到其左边最近的小于此数 的数
那么就是使得栈有单调性就可以
传送门
#include
using namespace std;
const int N=1e5+10;
int sta[N],tt;
int main(){
int n,x;
scanf("%d",&n);
for(int i=0;i=x)tt--;//清除队列中比x大的数字
if(tt)printf("%d ",sta[tt]);
else printf("-1 ");
sta[++tt]=x; //x入栈
}
return 0;
}
单调队列
注意滑动窗口的滑出情况和单调情况即可
q[hh]
a[q[tt]]>=a[i]使得队列递增
传送门
#include
using namespace std;
const int N=1e6+10;
int q[N],a[N];
int main(){
int n,k;
scanf("%d%d",&n,&k);
for(int i=0;iq[hh])hh++;//滑动窗口左端滑出
while(hh<=tt&&a[q[tt]]>=a[i])tt--;
q[++tt]=i;
if(i>=k-1)printf("%d ",a[q[hh]]);
}
puts("");
tt=-1,hh=0;
for(int i=0;i=a[q[tt]])tt--;
q[++tt]=i;
if(i>=k-1)printf("%d ",a[q[hh]]);
}
puts("");
return 0;
}
关于KMP
以前我写的东西,自己现在也不想看了。。。
这个过程还是很复杂的
大概就是next[i]数组存放的是以i为终点的与前缀相同的长度
然后匹配目标串时就可以通过j=ne[j]来快速移动模式串
求next数组过程和匹配的过程一样,求next数组时注意要从2开始
还有不能用next编码
i、j从1开始计算,因为当j==0时,j=ne[j]是无意义的
传送门
#include
using namespace std;
const int N=1e5+10,M=1e6+10;
char p[N],s[M];
int n,m,ne[N];
int main(){
cin>>n>>p+1>>m>>s+1;
for(int i=2,j=0;i<=n;i++){
while(j&&p[i]!=p[j+1])j=ne[j];
if(p[i]==p[j+1])j++;
ne[i]=j;
}
for(int i=1,j=0;i<=m;i++){
while(j&&s[i]!=p[j+1])j=ne[j];
if(s[i]==p[j+1])j++;
if(j==n){
printf("%d ",i-n);
}
}
return 0;
}