前言:
创作日期:2024/4/10,预计结束时间:20天,目的:巩固所学。
数据结构:
第一章:链表
概要:1、单链表。2、循环链表。3、双链表。
#include <bits/stdc++.h>
#define MAXSIZE 100
using namespace std;
typedef struct ListNode {
int data;
ListNode* nextNode;
} Node;
void init(Node* head) {
head->nextNode = nullptr;
}
void delete_(Node* head, int position) {
Node* curr = head;
int cnt = 0;
while (curr->nextNode != nullptr) {
cnt++;
if (cnt == position) {
Node* temp = curr->nextNode;
curr->nextNode = temp->nextNode;
delete (temp);
return ;
}
curr = curr->nextNode;
}
}
void print(Node* head) {
Node* curr = head->nextNode;
while (curr != nullptr) {
cout << curr->data << " ";
curr = curr->nextNode;
}
cout << endl;
}
void modify(Node* head, int position, int val) {
Node* curr=head;
int cnt=0;
while(curr->nextNode!=nullptr) {
cnt++;
if(cnt==position) {
curr->nextNode->data=val;
return ;
}
curr=curr->nextNode;
}
}
void headInsert(Node* head, int val) {
Node* curr = head;
Node* newNode = new (Node);
newNode->data = val;
newNode->nextNode = curr->nextNode;
curr->nextNode = newNode;
}
void tailInstert(Node* head, int val) {
Node* curr=head;
while(curr->nextNode!=nullptr) {
curr=curr->nextNode;
}
Node* newNode=new(Node);
newNode->data=val;
newNode->nextNode=nullptr;
curr->nextNode=newNode;
}
void destroy(Node* head) {
Node* curr=head->nextNode;
while(curr!=nullptr) {
Node* temp=curr;
curr=curr->nextNode;
delete(temp);
}
head->nextNode=nullptr;
}
void isEmpty(Node* head) {
if (head->nextNode == nullptr)
cout << "EMPTY LIST!" << endl;
}
int listSize(Node* head) {
Node* curr=head;
int cnt=0;
while(curr->nextNode!=nullptr) {
curr=curr->nextNode;
cnt++;
}
return cnt;
}
int main() {
Node* head = new (Node);
init(head);
isEmpty(head);
headInsert(head, 1);
headInsert(head, 2);
headInsert(head, 3);
print(head);
delete_(head, 2);
print(head);
tailInstert(head, 4);
tailInstert(head, 5);
print(head);
modify(head, 3, 6);
print(head);
cout<<listSize(head)<<endl;
destroy(head);
isEmpty(head);
return 0;
}
单链表:
#include <bits/stdc++.h>
#define elemtype int
#define N 10
using namespace std;
typedef struct LinkList{
elemtype data;
LinkList* next;
} L;
elemtype tail_insert(L* head, int val) {
L* curr=head;
L* newNode=new(L);
if(!curr->next) {
curr->next=newNode;
} else {
while(curr->next!=nullptr) {
curr=curr->next;
}
curr->next=newNode;
}
newNode->data=val;
return 1;
}
elemtype head_insert(L* head, int val) {
L* curr=head;
L* newNode=new(L);
if(!curr->next) {
curr->next=newNode;
} else {
L* temp=curr->next;
curr->next=newNode;
newNode->next=temp;
}
newNode->data=val;
return 1;
}
bool list_empty(L* head) {
return head->next==nullptr;
}
void list_print(L* head) {
if(list_empty(head))
return ;
L* curr=head;
while(curr!=nullptr) {
cout<<curr->data<<"->";
curr=curr->next;
}
cout<<"nullptr";
}
elemtype list_length(L* head) {
L* curr=head;
int cnt=0;
while(curr->next!=nullptr) {
cnt++;
}
return cnt;
}
elemtype find(L* head, int key) {
if(key<0 || key>=list_length(head)) {
throw out_of_range("索引越界。");
}
L* curr=head;
int i=0;
while(i!=key) {
i++;
curr=curr->next;
}
return curr->data;
}
int main() {
L* head=new(L);
int value=6;
tail_insert(head, value);
return 0;
}
第二章:栈
顺序栈:
#include <bits/stdc++.h>
#define elemtype int
#define size 10
using namespace std;
typedef struct Stack {
elemtype data[size];
elemtype top;
} S;
void initStack(S* s) {
s->top=-1;
}
bool isEmpty(S* s) {
return s->top==-1;
}
bool isFull(S* s) {
return s->top==size-1;
}
int push(S* s, elemtype val) {
if(isFull(s)) {
throw out_of_range("栈满。");
}
s->data[s->top++]=val;
return 1;
}
int pop(S* s) {
if(isEmpty(s)) {
throw out_of_range("栈空");
}
return s->data[s->top--];
}
int main() {
S* s=new(S);
initStack(s);
return 0;
}
链栈:
第三章:队列
顺序队列:
#include <bits/stdc++.h>
#define size 10
using namespace std;
typedef struct Queue {
int data[size];
int front, rear;
} Q;
void init(Q* q) {
q->front=0, q->rear=0;
}
bool isEmpty(Q* q) {
return q->front==q->rear;
}
bool isFull(Q* q) {
return q->rear==size-1;
}
void enQueue(Q* q, int val) {
if(isFull(q)) {
return ;
}
q->data[q->rear++]=val;
}
int deQueue(Q* q) {
if(isEmpty(q)) {
cout<<"empty queue!"<<endl;
return -1;
}
return q->data[q->front++];
}
int getFront(Q* q) {
return q->data[q->front];
}
int main() {
Q* q=new(Q);
init(q);
enQueue(q, 2);
enQueue(q, 1);
cout<<getFront(q)<<endl;
deQueue(q);
cout<<getFront(q)<<endl;
return 0;
}
链队:
循环队列:
#include <bits/stdc++.h>
#define size 10
using namespace std;
//循环队列
typedef struct Queue {
int data[size];
int front, rear;
} Q;
void init(Q* q) {
q->front=0;
q->rear=0;
}
bool isEmpty(Q* q) {
return q->rear==q->front;
}
bool isFull(Q* q) {
return q->rear==size-1;
}
void enQueue(Q* q, int val) {
if(isFull(q)) {
return ;
}
q->data[q->rear]=val;
q->rear=(q->rear+1)%size;
}
int deQueue(Q* q) {
if(isEmpty(q)) {
cout<<"empty queue!"<<endl;
return -1;
}
int ans=q->data[q->front];
q->front=(q->front+1)%size;
return ans;
}
int getFront(Q* q) {
if(isEmpty(q)) {
cout<<"empty queue!"<<endl;
return -1;
}
return q->data[q->front];
}
void clear(Q* q) {//clear()可以直接将队内元素出队,然后再delete队列q即可
while(!isEmpty(q)) {
deQueue(q);
}
delete q;
q=nullptr;//删除q之后,防止再次调用q时引发内存问题
}
int main() {
Q* q=new(Q);
init(q);
enQueue(q, 4);
enQueue(q, 5);
cout<<getFront(q)<<endl;
deQueue(q);
cout<<getFront(q)<<endl;
clear(q);
cout<<getFront(q);
return 0;
}
第四章:堆
第五章:串
第六章:树
二叉树的前、中、后序遍历(递归版):
#include <bits/stdc++.h>
using namespace std;
typedef struct BinaryTree {
char data;
BinaryTree* lchild, * rchild;
} BT;
void create(BT** node) {
char input;
cin>>input;
if(input=='#')
*node=nullptr;
else {
*node=new(BT);
(*node)->data=input;
create(&(*node)->lchild);
create(&(*node)->rchild);
}
}
void preOrder(BT* root) {
if(root==nullptr)
return ;
cout<<root->data<<" ";
preOrder(root->lchild);
preOrder(root->rchild);
}
void inOrder(BT* root) {
if(root==nullptr)
return ;
inOrder(root->lchild);
cout<<root->data<<" ";
inOrder(root->rchild);
}
void posOrder(BT* root) {
if(root==nullptr)
return ;
posOrder(root->lchild);
posOrder(root->rchild);
cout<<root->data<<" ";
}
int main() {
BT* root;
create(&root);
preOrder(root);
cout<<endl;
inOrder(root);
cout<<endl;
posOrder(root);
return 0;
}
//abd##e##cf##g##
二叉树的前、中、后序遍历(非递归版):
#include <bits/stdc++.h>
using namespace std;
typedef struct BinaryTree {
char data;
BinaryTree* lchild, * rchild;
} BT;
void create(BT** node) {//建立二叉树,按照中序的顺序建立结点
char input;
cin>>input;
if(input=='#') {
*node=nullptr;
} else {
*node=new(BT);
(*node)->data=input;
create(&(*node)->lchild);
create(&(*node)->rchild);
}
}
void preOrder(BT* root) {//前序遍历非递归
stack<BT*> s;
BT* curr;
s.push(root);
while(!s.empty()) {
curr=s.top();
s.pop();
cout<<curr->data<<" ";
if(curr->rchild!=nullptr) {//先入右儿子
s.push(curr->rchild);
}
if(curr->lchild!=nullptr) {//再入左儿子
s.push(curr->lchild);
}
}
}
void inOrder(BT* root) {//中序遍历非递归
stack<BT*> s;
BT* curr=root;
while(!s.empty() || curr!=nullptr) {
if(curr!=nullptr) {//将二叉树的左子树全部入栈
s.push(curr);
curr=curr->lchild;
} else {//直到没有左子树就进行弹栈
curr=s.top();
s.pop();
cout<<curr->data<<" ";//因为是中序遍历所以在弹栈后将curr指针跳到刚弹出的元素的右儿子上
curr=curr->rchild;
}
}
}
void posOrder(BT* root) {
stack<BT*> s;
stack<BT*> collect;
BT* curr;
s.push(root);
while(!s.empty()) {
curr=s.top();
s.pop();
collect.push(curr);
if(curr->lchild!=nullptr) {
s.push(curr->lchild);
}
if(curr->rchild!=nullptr) {
s.push(curr->rchild);
}
}
while(!collect.empty()) {
cout<<collect.top()->data<<" ";
collect.pop();
}
}
int main() {
BT* root;
create(&root);
preOrder(root);
cout<<endl;
inOrder(root);
cout<<endl;
posOrder(root);
return 0;
}
//abd##e##cf##g##
二叉树的层序遍历:
#include <bits/stdc++.h>
using namespace std;
typedef struct BinaryTree {
char data;
BinaryTree* lchild, * rchild;
} BT;
void create(BT** node) {
char input;
cin>>input;
if(input=='#')
*node=nullptr;
else {
*node=new(BT);
(*node)->data=input;
create(&(*node)->lchild);
create(&(*node)->rchild);
}
}
void levelOrder(BT* root) {//层序遍历
queue<BT*> q;
q.push(root);
BT* curr;
while(!q.empty()) {
curr=q.front();
q.pop();
cout<<curr->data<<" ";
if(curr->lchild!=nullptr) {
q.push(curr->lchild);
}
if(curr->rchild!=nullptr) {
q.push(curr->rchild);
}
}
}
int main() {
BT* root;
create(&root);
levelOrder(root);
return 0;
}
//abd##e##cf##g##
求二叉树的最大高度和最小高度:
#include <bits/stdc++.h>
using namespace std;
typedef struct Binary_tree {
char data;
Binary_tree* lchild, * rchild;
} BT;
void create(BT** node) {
char input;
cin>>input;
if(input=='#') {
*node=nullptr;
} else {
*node=new(BT);
(*node)->data=input;
create(&(*node)->lchild);
create(&(*node)->rchild);
}
}
//void levelOrder(BT* root) {
// queue<BT*> q;
// BT* curr=nullptr;
// q.push(root);
// while(!q.empty()) {
// curr=q.front();
// cout<<curr->data;
// q.pop();
// if(curr->lchild!=nullptr)
// q.push(curr->lchild);
// if(curr->rchild!=nullptr)
// q.push(curr->rchild);
// }
//}
int maxDepth(BT* root) {
return root==nullptr? 0: max(maxDepth(root->lchild), maxDepth(root->rchild))+1;
}
int minDepth(BT* root) {
//空树直接返回
if(root==nullptr)
return 0;
//叶子节点
if(root->lchild==nullptr && root->rchild==nullptr)
return 1;
int ldeep=65000;//左子树的高度设为极大数,代表还未查找
int rdeep=65000;
if(root->lchild!=nullptr)
ldeep=minDepth(root->lchild);
if(root->rchild!=nullptr)
rdeep=minDepth(root->rchild);
return min(ldeep, rdeep)+1;
}
int main() {
BT* root;
create(&root);
// levelOrder(root);
int deep=maxDepth(root);
cout<<deep<<endl;
deep=minDepth(root);
cout<<deep;
return 0;
}
//abd##e##c##
并查集://解决蓝桥杯国赛-合根植物24.4.29
#include <bits/stdc++.h>
#define ll long long
#define N 10005
using namespace std;
//并查集模板
//sample,需要改进
ll father[N], size[N], pre[N];
void init() {//初始化father数组,将每个数组的头都指向自己
for(int i=0; i<N; i++) {
father[i]=i;
}
}
int find_(int i) {//寻找头
if(father[i]==i) {//如果该点的头就是他自己,直接返回
return i;
}
return father[i]=find_(father[i]);//否则递归查找头结点
}
bool sameRoot(int x, int y) {//判断x和y结点是不是在一个头上
return find_(x)==find_(y);//调用fine_()进行判断,find_()会找到各自结点的最大头
}
void union_(int x, int y) {//将x和y结点连接在一个头上
if(!sameRoot(x, y)) {//如果不在一个头上
father[find_(x)]=find_(y);//用find_()找到x的最大头节点,随后连接到了y的头结点上
}
}
int main() {
return 0;
}
第七章:图
算法通关:
第一章:链表的经典算法
第二章:栈的经典算法
单调栈:
#include <bits/stdc++.h>
using namespace std;
//蓝桥杯_百亿富翁
stack<int> s;
int arr[5]= {3, 1, 2, 5, 4};
int ans[5];
int main() {
for(int i=0; i<5; i++) {
while(!s.empty() && arr[i]>=arr[s.top()]) {
s.pop();
}
ans[i]=s.empty()? -1:s.top();
s.push(i);
}
for(int i=0; i<5; i++) {
cout<<ans[i]<<" ";
}
cout<<endl;
while(!s.empty()) {
s.pop();
}
memset(ans, 0, sizeof(ans));
for(int i=4; i>=0; i--) {
while(!s.empty() && arr[i]>=arr[s.top()]) {
s.pop();
}
ans[i]=s.empty()? -1:s.top();
s.push(i);
}
for(int i=0; i<5; i++) {
cout<<ans[i]<<" ";
}
return 0;
}
第三章:队列的经典算法
第四章:堆的经典算法
第五章:串的经典算法
bf算法(brute force):
kmp算法:
#include <bits/stdc++.h>
#define N 20
using namespace std;
int nexta[N];
string s1="abababcc";
string s2="cc";
void getnext() {
int len=s2.length();
nexta[0]=-1, nexta[1]=0;
int curr=2, cn=0;
while(curr<len) {
if(s2[curr-1]==s2[cn]) {
nexta[curr++]=++cn;
} else if(cn>0) {
cn=nexta[cn];
} else {
nexta[curr++]=0;
}
}
}
int kmp() {
int lenS1=s1.length();
int lenS2=s2.length();
int x=0, y=0;
getnext();
while(x<lenS1 && y<lenS2) {
if(s1[x]==s2[y]) {
x++, y++;
} else if(y==0) {
x++;
} else {
y=nexta[y];
}
}
return y==lenS2 ? x-y : -1;
}
int main() {
int ans=kmp();
cout<<ans;
return 0;
}
第六章:树的经典算法
第七章:图的经典算法
bfs(广度优先搜索):
迷宫问题:
#include <bits/stdc++.h>
#define N 4
using namespace std;
int maze[N][N]= { {0, 1, 1, 1}, {0, 0, 0, 0}, {1, 1, 1, 0}, {0, 0, 0, 0} };
int vis[N][N]={0};
pair<int, int> pre[N][N];
int dx[4]={0, 1, 0, -1};
int dy[4]={1, 0, -1, 0};
queue<pair<int, int>> q;
stack<pair<int, int>> s;
int startx=0, starty=0, endx=N-1, endy=N-1;
void bfs() {
q.push({startx, starty});
vis[startx][starty]=1;
while(!q.empty()) {
int x=q.front().first;
int y=q.front().second;
q.pop();
if(x==endx && y==endy) {
return ;
}
for(int i=0; i<4; i++) {
int tx=dx[i]+x;
int ty=dy[i]+y;
if(tx>=0 && tx<N && ty>=0 && ty<N && maze[tx][ty]==0 && vis[tx][ty]==0) {
q.push({tx, ty});
vis[tx][ty]=1;
pre[tx][ty]={x, y};
}
}
}
}
void path() {
int x=endx, y=endy;
pair<int, int> curr;
while(x!=startx || y!=starty) {
s.push({x, y});
curr=pre[x][y];
x=curr.first;
y=curr.second;
}
s.push({startx, starty});
while(!s.empty()) {
cout<<s.top().first<<","<<s.top().second<<endl;
s.pop();
}
}
int main() {
bfs();
path();
return 0;
}
dfs(深度优先搜索):
迷宫问题:
#include <bits/stdc++.h>
#define N 4
using namespace std;
//dfs迷宫+路径回溯
int maze[N][N]={
{0, 1, 1, 1},
{0, 0, 0, 0},
{1, 0, 0, 1},
{1, 0, 0, 0}
};
int dx[4]={0, 1, 0, -1};
int dy[4]={1, 0, -1, 0};
int vis[N][N]={0};
int stx=0, sty=0, edx=N-1, edy=N-1;
int minStep=99;
stack<pair<int, int>> s;
pair<int, int> pre[N][N];
void dfs(int x, int y, int step) {
if(x==edx && y==edy) {
minStep=min(minStep, step);
return ;
}
for(int i=0; i<4; i++) {
int tx=dx[i]+x;
int ty=dy[i]+y;
if(tx>=0 && tx<N && ty>=0 && ty<N && maze[tx][ty]==0 && vis[tx][ty]==0) {
vis[tx][ty]=1;
pre[tx][ty]={x, y};
dfs(tx, ty, step+1);
vis[tx][ty]=0;
}
}
return ;
}
void path() {
int x=edx, y=edy;
pair<int, int> curr;
while(x!=stx || y!=sty) {
s.push({x, y});
curr=pre[x][y];
x=pre[x][y].first;
y=pre[x][y].second;
}
s.push({stx, sty});
while(!s.empty()) {
cout<<s.top().first<<","<<s.top().second<<endl;
s.pop();
}
}
int main() {
dfs(0, 0, 0);
cout<<minStep<<endl;
path();
return 0;
}
最小生成树:
Kruskal:
//https://www.luogu.com.cn/problem/P3366
#include <bits/stdc++.h>
#define M 200010
#define ll long long
using namespace std;
//Kruskal
int fa[M], edge[M][3];
ll n, m, x, y, z;
void build() {
for (int i = 0; i < M; i++) {
fa[i] = i;
}
}
int find_(int i) {
if (fa[i] == i)
return i;
return fa[i] = find_(fa[i]);
}
bool isSameRoot(int x, int y) {
return find_(x) == find_(y);
}
bool union_(int x, int y) {
if (!isSameRoot(x, y)) {
fa[find_(x)] = find_(y);
return true;
}
return false;
}
int cmp(const void* a, const void* b) {
int* n1=(int* )a;
int* n2=(int* )b;
return n1[2]-n2[2];
}
int main() {
build();
cin>>n>>m;
for(int i=0; i<m; i++) {
cin>>x>>y>>z;
edge[i][0]=x;
edge[i][1]=y;
edge[i][2]=z;
}
qsort(edge, m, sizeof(int[3]), cmp);
int cnt=0, ans=0;
for(int i=0; i<m; i++) {
if(union_(edge[i][0], edge[i][1])) {
cnt++;
ans+=edge[i][2];
}
}
cnt==n-1? cout<<ans: cout<<"orz";
return 0;
}
拓展:其他算法
二分查找:
二分答案:
一维差分:
#include <bits/stdc++.h>
#define N 7
using namespace std;
//一维差分
//需要在数组实际数据的大小上额外开辟2个空间用于差分操作,实际数据从下标为1的地址上开始存储
int arr[N]={0, 2, 2, 2, 1, 5, 0};
int diff[N]={0};
int main() {
//加工差分数组
for(int i=1; i<N; i++) {
diff[i]=arr[i]-arr[i-1];
}
int times=2, l, r, x;
//times:对数组进行加减操作的次数。
while(times--) {
cin>>l>>r>>x;
diff[l]+=x;
diff[r+1]-=x;
}
//求前缀和还原差分数组
for(int i=1; i<N; i++) {
diff[i]+=diff[i-1];
}
for(int i=1; i<N-1; i++) {
cout<<diff[i]<<" ";
}
return 0;
}
动态规划(dp):
斐波那契数列:
#include <bits/stdc++.h>
#define N 20
using namespace std;
//dp_斐波那契数列
int dp[N];
int main() {
dp[0]=0, dp[1]=1, dp[2]=1;
for(int i=2; i<=N; i++) {
dp[i]=dp[i-1]+dp[i-2];
}
for(int i=0; i<=N; i++) {
cout<<dp[i]<<" ";
}
return 0;
}
背包问题:
01背包:
#include <bits/stdc++.h>
#define MAX 1001
using namespace std;
//蓝桥杯题库:小明的背包1
int w[MAX], v[MAX];
int N, V;
int dp[MAX+1][MAX+1]={0};//放在main()中间会因为空间不足而dead
int main() {
cin>>N>>V;
for(int i=1; i<=N; i++) {
cin>>v[i]>>w[i];
}
for(int i=1; i<=N; i++) {
for(int j=1; j<=V; j++) {
if(j<v[i]) {//拿不下,背包空间小于当前物品的体积
dp[i][j]=dp[i-1][j];
} else {
dp[i][j]=max(dp[i-1][j], dp[i-1][j-v[i]]+w[i]);
}
}
}
cout<<dp[N][V];
return 0;
}
高精度算法:
高精度加法:
#include <bits/stdc++.h>
using namespace std;
//高精度加法
string s1, s2;
int num1[1000], num2[1000];
int main() {
cin>>s1>>s2;
reverse(s1.begin(), s1.end());
reverse(s2.begin(), s2.end());
int len1=s1.length(), len2=s2.length();
for(int i=0; i<len1; i++) {
num1[i]=s1[i]-'0';//得到数值
}
for(int i=0; i<len2; i++) {
num2[i]=s2[i]-'0';
}
int size=max(len1, len2)+1;//多加一位,在进位时可以保证位数
// cout<<size;
int ans[size]={0}, carry=0;
for(int i=0; i<max(len1, len2); i++) {
ans[i]=num1[i]+num2[i]+carry;
carry=ans[i]/10;
ans[i]%=10;
}
if(carry>0) {//控制最高位,如果carry到最后都还>0则说明要向最高位进位,否则就将最高位不计入
ans[size-1]=carry;
} else {
size--;
}
for(int i=size-1; i>=0; i--) {//反向打印数组
cout<<ans[i];
}
return 0;
}
高精度减法:
#include <bits/stdc++.h>
using namespace std;
//高精度减法
string s1, s2;
int num1[1000], num2[1000];
bool cmp(string s1, string s2) {
if (s1.length() < s2.length() || s1.length() == s2.length() && s1 < s2) {
swap(s1, s2);
return true;
}
return false;
}
int main() {
cin >> s1 >> s2;
bool flag = cmp(s1, s2);
// cout<<s1<<endl<<s2;
int len1 = s1.length(), len2 = s2.length();
reverse(s1.begin(), s1.end()), reverse(s2.begin(), s2.end());
for (int i = 0; i < len1; i++)
num1[i] = s1[i] - '0';
for (int i = 0; i < len2; i++)
num2[i] = s2[i] - '0';
int size = max(len1, len2);
int ans[size];
if (!flag) {
for (int i = 0; i < size; i++) {
if (num1[i] - num2[i] < 0) {
num1[i + 1]--;
num1[i] += 10;
}
ans[i] = num1[i] - num2[i];
}
} else {
cout << "-";
for (int i = 0; i < size; i++) {
if (num2[i] - num1[i] < 0) {
num2[i + 1]--;
num2[i] += 10;
}
ans[i] = num2[i] - num1[i];
}
}
while (ans[size - 1] == 0) {
size--;
}
for (int i = size - 1; i >= 0; i--) {
cout << ans[i];
}
return 0;
}
高精度乘法:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
string a, b;
cin >> a >> b;
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int lenA = a.length();
int lenB = b.length();
int A[2000], B[2000], C[2010] = {0}; // 初始化 C 数组
for (int i = 0; i < lenA; i++) {
A[i] = a[i] - '0';
}
for (int i = 0; i < lenB; i++) {
B[i] = b[i] - '0';
}
int lenC = lenA + lenB;
// 模拟乘法
for (int i = 0; i < lenA; i++) {
for (int j = 0; j < lenB; j++) {
C[i + j] += A[i] * B[j]; // 这里修正为 C[i+j]
C[i + j + 1] += C[i + j] / 10; // 处理进位
C[i + j] %= 10; // 当前位
}
}
// 处理结果长度
while (lenC > 0 && C[lenC - 1] == 0) lenC--; // 去除前导零
if (lenC == 0) cout << 0; // 如果结果为0
else {
for (int i = lenC - 1; i >= 0; i--) {
cout << C[i];
}
}
return 0;
}
前缀:
前缀树:
#include <bits/stdc++.h>
#define MAXN 15000
//前缀树
using namespace std;
int tree[MAXN][26];//a to z 26 letters
int end_[MAXN];//end在cpp是关键字
int pass[MAXN];
int cnt;
void build() {
cnt = 1;
}
void insert(string word) {
int curr = 1;
pass[curr]++;
for (int i = 0, path; i < word.size(); i++) {
path = (char)word[i] - 'a';
if (tree[curr][path] == 0) {
tree[curr][path] = ++cnt;
}
curr = tree[curr][path];
pass[curr]++;
}
end_[curr]++;
}
int search(string word) {//按照整个字符串查找
int curr = 1;
for (int i = 0, path; i < word.size(); i++) {
path = (char)word[i] - 'a';
if (tree[curr][path] == 0) {
return 0;
}
curr = tree[curr][path];
}
return end_[curr];
}
int prefixNumber(string pre) {//按照前缀信息查找
int curr=1;
for(int i=0, path; i<pre.size(); i++) {
path=(char)pre[i]-'a';
if(tree[curr][path]==0) {
return 0;
}
curr=tree[curr][path];
}
return pass[curr];
}
void delete_(string word) {
if (search(word) > 0) {//如果没有这个字符串直接返回
int curr = 1;
for (int i = 0, path; i < word.size(); i++) {
path = (char)word[i] - 'a';//找出字符串每个字符的路径
if(--pass[tree[curr][path]]==0) {//找出对应路径后让--pass,减少路径信息
tree[curr][path]=0;//如果某条路径信息删除后为0,那么直接断开后面的路径
return ;
}
curr=tree[curr][path];
}
end_[curr]--;//找到最后的情况,使end_[]--
}
}
int main() {
build();
int m;
cin>>m;
while(m--) {
int op;
string word;
cin>>op>>word;
switch (op) {
case 1:
insert(word);
break;
case 2:
delete_(word);
break;
case 3:
if(search(word))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
break;
case 4:
cout<<prefixNumber(word)<<endl;
}
}
return 0;
}