知识点 : 链表与邻接表 . 栈与队列 . kmp
链表
1.单链表
//head[]表示链表头,e[]表示节点,ne[]表示next指针,idx表示当前点
int head,e[N],ne[N],idx;
void init(){
head = -1;
idx = 0;
}
//在头节点插入一个数
void insert(int a){
e[idx] = a;ne[idx] = head;head = idx++;
}
//删除头节点
void remove(){
head = ne[head];
}
//将x插到k节点的后面
void add(int k,int x){
e[idx] = x;
ne[idx] = ne[k];
ne[k] = idx;
idx ++;
}
//将k结点后面的数字删除
void remove(int k){
ne[k] = ne[ne[k]];
}
//遍历:
for(int i = head;i != -1;i = ne[i])cout << e[i] << " ";
2.双链表
//该点的值,该点的左点,该点的右点,当前的下标
int e[N],l[N],r[N],idx;
void init(){
//0表示左端点,1表示右端点
r[0] = 1,l[1] = 0;
idx = 2;
}
//在下标是k的点的右边,插入x
//在k的左边插入等于在l[k]的右边插入
void add(int k,int x){
e[idx] = x;
r[idx] = r[k];
l[idx] = k;
l[r[k]] = idx;
r[k] = idx;
}
//删除第k个点
void remove(int k){
r[l[k]] = r[k];
l[r[k]] = l[k];
}
栈与队列
1.栈
//模拟栈,tt表示栈顶
int stk[N],tt;
//栈顶插入
stk[++tt] = x;
//栈顶弹出
tt--;
//判断栈是否为空
if(tt > 0){
}
2.队列
//在队尾插入元素,在队头弹出元素
int q[N],hh,tt = -1;
//队尾插入
q[++tt] = x;
//队头弹出
hh++;
//是否为空
if(hh <= tt){
}
//取出队头
q[hh]
3.单调栈问题
找到一个序列中每个数左边离他最近的比他大/小的数 .
优化
//找到每个数左边离他最近的,比他小的数
int n,stk[N],tt;
int main(){
cin >> n;
for(int i=0;i<n;i++){
int x;cin >> x;
while(tt && stk[tt] >= x)tt--;
if(tt)cout << skt[tt];
else cout << "-1";
stk[++tt] = x;
}
return 0;
}
4.单调队列
滑动窗口,输出一个窗口中最大值和最小值
优化 : 如果求最小值,枚举到i时,如果队列的尾部比a[i]大,去掉尾部,再把a[i]放进去,头部维护最小值的下标
//单调队列
int a[N],q[N],n,k; //q记录对应下标
int main(){
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
int hh = 0,tt = -1;
for(int i=0;i<n;i++){ //最小值
//如果队列中有元素 而且 队头划出了窗口
if(hh <= tt && i - k + 1 > q[hh])hh++;
//把队列中比a[i]大的元素全弹出
while(hh <= tt && a[q[tt]] >= a[i])tt--;
q[++tt] = i;
if(i >= k - 1)printf("%d ",a[q[hh]]);
}
puts("");
hh = 0,tt = -1;
for(int i=0;i<n;i++){ //最大值
//如果队列中有元素 而且 队头划出了窗口
if(hh <= tt && i - k + 1 > q[hh])hh++;
//把队列中比a[i]小的元素全弹出
while(hh <= tt && a[q[tt]] <= a[i])tt--;
q[++tt] = i;
if(i >= k - 1)printf("%d ",a[q[hh]]);
}
return 0;
}
kmp算法
求模板串p在S中所有出现的下标
例如 aba 在 ababa中的下标为 0 2.
预处理 : 找到模板串p中,某一段前缀和后缀相同,找最长的.
next[i] = j 表示 p[1 ~ j] == p[ i - j + 1 ~ i] , 以i为终点前面这一段最少的移动距离,直接调用
例如 : p = “abababab”,ne[1] = 0,ne[2] =0 ,ne[3] = 1, ne[6] = 4,表示在ababab中.1 ~4 等于3 ~ 6.
const int N = 10010,M = 100010;
int n,m;
char p[N],s[M];
int ne[N];
int main(){
cin >> n >> p+1 >> m >> s+1;
//求ne[]
ne[1] = 0;
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);
j = ne[j];
}
}
return 0;
}