数据结构之串

数据结构之串(String)

  • 数据结构之串(String)
    • 1. 串的定义
    • 2. 串的存储结构
      • 2.1 顺序存储
      • 2.2 链式存储
      • 2.3 索引存储
    • 3. 串的常见操作
      • 3.1 基本操作
        • 3.1.1 创建串
        • 3.1.2 求串长度
        • 3.1.3 串连接
        • 3.1.4 串比较
        • 3.1.5 串拷贝
      • 3.2 高级操作
        • 3.2.1 查找子串
          • BF算法(Brute Force)
          • KMP算法(Knuth-Morris-Pratt)
            • 核心思想
            • 构造前缀表
            • KMP 主串匹配
            • 测试代码
        • 3.2.2 插入子串
        • 3.2.3 删除子串
        • 3.3.4 替换子串
    • 4. 串的存储实现与代码示例
    • 5. 串的实际应用

数据结构之串(String)

在数据结构中,串(String) 是一种用于表示和操作字符序列的结构。它是最基本的线性表类型之一,广泛应用于文本处理、模式匹配、字符串操作等领域。


1. 串的定义

是由零个或多个字符组成的有限序列,也可以称为字符串。例如:

  • 空串:长度为零的串。
  • 非空串:如 "abc""数据结构"

一个串通常表示为:

S = "a1a2a3...an" (n >= 0)

其中,a1, a2, ..., an 是串中的字符,n 为串的长度。字符可以是字母、数字、符号、空格等任意字符。

串的相关概念

  1. 空串 (Null String)

    • 长度为 0 的串。
    • 空串与 NULL 不同,空串是合法的字符串对象,只是内容为空。
  2. 空格串 (Blank String)

    • 由一个或多个空格字符组成的串,例如 " "
    • 空格串的长度大于等于 1。
  3. 子串 (Substring)

    • 串中任意连续字符组成的子序列称为该串的“子串”。
    • 子串可为空串。例如,"abc" 的子串包括 "a", "ab", "bc", 以及空串 ""
  4. 主串 (Master String)

    • 包含子串的串称为“主串”。例如,"abcde" 是子串 "bcd" 的主串。
  5. 串的长度 (Length)

    • 串中所包含字符的个数,不包含结束标记 \0
  6. 前缀 (Prefix)

    • 一个字符串的前缀是从第一个字符开始到某个字符位置的子串。例如,"abc" 的前缀有:"""a""ab"
  7. 后缀 (Suffix)

    • 一个字符串的后缀是从某个字符位置到最后一个字符的子串。例如,"abc" 的后缀有:"""c""bc"

2. 串的存储结构

根据串的存储形式,常见的实现方式有以下几种:

2.1 顺序存储

  • 将串的字符按顺序存储在一块连续的存储空间中。
  • 优点:支持随机访问,操作效率高。
  • 缺点:插入和删除操作需要移动大量字符,效率较低。
char str[100]; // 单纯的字符数组

2.2 链式存储

  • 使用链表存储串的字符,每个节点存储一个字符。
  • 优点:支持动态扩展,插入和删除操作较快。
  • 缺点:占用额外的存储空间,随机访问效率较低。
typedef struct StringNode {char data;struct StringNode *next;
} StringNode;

2.3 索引存储

  • 将串分段存储,同时使用索引表记录每段的起始地址。
  • 优点:适合处理超大字符串,分段加载,节省内存。
  • 缺点:管理复杂度较高。
#define MAX_SEGMENT_LENGTH 50 // 每个段的最大长度
#define MAX_SEGMENTS 10       // 最大段数typedef struct {char *data;              // 存储段的数据
} Segment;typedef struct {Segment segments[MAX_SEGMENTS]; // 存储多个段int segmentCount;               // 当前段数
} IndexString;

3. 串的常见操作

3.1 基本操作

3.1.1 创建串

初始化字符串。

typedef struct {char mem[1024]; // 用于存储字符的数组int curSize;    // 当前字符串长度
} String, *LPSTR;// 创建字符串
LPSTR createstring(const char *str) {LPSTR pstr = (LPSTR)malloc(sizeof(String));assert(pstr);memset(pstr->mem, '\0', 1024); // 初始化数组int count = 0;while (str[count] != '\0' && count < 1024) {pstr->mem[count] = str[count];count++;}pstr->curSize = count; // 更新当前长度return pstr;
}// 打印字符串
void printstring(LPSTR pstr) {for (int i = 0; i < pstr->curSize; i++) {putchar(pstr->mem[i]);}putchar('\n');
}
3.1.2 求串长度

返回字符串中字符的个数。

// 求串长度
int getlength(LPSTR pstr) {return pstr->curSize;
}
3.1.3 串连接

将两个字符串拼接为一个字符串。

// 串连接
void concatstring(LPSTR dest, const char *src) {int srcLen = strlen(src);if (dest->curSize + srcLen >= 1024) {printf("字符串过长,无法连接!\n");return;}for (int i = 0; i < srcLen; i++) {dest->mem[dest->curSize + i] = src[i];}dest->curSize += srcLen;
}
3.1.4 串比较

比较两个字符串的大小(字典顺序)。

// 串比较
int comparestring(LPSTR str1, LPSTR str2) {return strcmp(str1->mem, str2->mem);
}
3.1.5 串拷贝

将一个字符串复制到另一个字符串中。

// 串拷贝
void copystring(LPSTR dest, LPSTR src) {memset(dest->mem, '\0', 1024); // 清空目标串for (int i = 0; i < src->curSize; i++) {dest->mem[i] = src->mem[i];}dest->curSize = src->curSize;
}

3.2 高级操作

3.2.1 查找子串
BF算法(Brute Force)

BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。BF算法是一种蛮力算法。

// 查找子串 - BF算法
int findsubstringBF(LPSTR mainStr, const char *pattern) {int m = mainStr->curSize; // 主串长度int n = strlen(pattern);  // 模式串长度for (int i = 0; i <= m - n; i++) {int j = 0;while (j < n && mainStr->mem[i + j] == pattern[j]) {j++;}if (j == n) {return i; // 返回匹配的起始位置}}return -1; // 未找到
}
KMP算法(Knuth-Morris-Pratt)

KMP算法是一种高效的字符串匹配算法,它的核心思想是利用已匹配的部分信息来避免重复匹配,从而提升匹配效率。相较于朴素的暴力匹配算法(BF算法),KMP在最坏情况下的时间复杂度为 O(m + n),其中 m 是主串长度,n 是模式串长度。


核心思想
  1. 前缀表 (Partial Match Table, PMT)

    • 前缀表存储的是模式串中每个位置之前的子串的“前缀”和“后缀”的最大匹配长度。
    • 前缀:子串的前面部分。
    • 后缀:子串的后面部分。
    • 例:"ababaca" 的前缀表如下:
      模式串:    a  b  a  b  a  c  a
      前缀表PMT: 0  0  1  2  3  0  1
      
      含义:在模式串的第 i 个字符时,前缀与后缀能匹配的最大长度为 PMT[i]
  2. 通过前缀表优化匹配

    • 当匹配失败时,不需要回退主串的匹配位置,而是通过前缀表直接跳转到模式串的某个位置继续匹配。
    • 这样可以避免重复匹配,从而提高效率。
构造前缀表

前缀表(也叫 next 数组)是 KMP 算法的核心,描述了模式串中每个字符之前的部分匹配信息。

// 计算模式串的前缀表 (next 数组)
void computePrefixTable(const char *pattern, int *next, int n) {next[0] = 0; // 第一个字符的前缀长度总是 0int len = 0; // 当前最长前缀的长度int i = 1;while (i < n) {if (pattern[i] == pattern[len]) {len++;next[i] = len;i++;} else {if (len > 0) {len = next[len - 1]; // 回溯到上一个最长前缀的位置} else {next[i] = 0;i++;}}}
}

示例:计算 "ababaca" 的前缀表

const char *pattern = "ababaca";
int next[7];
computePrefixTable(pattern, next, strlen(pattern));for (int i = 0; i < 7; i++) {printf("%d ", next[i]);  // 输出: 0 0 1 2 3 0 1
}
KMP 主串匹配

通过前缀表实现高效的字符串匹配。

// KMP 模式匹配
int KMP(const char *text, const char *pattern) {int m = strlen(text);    // 主串长度int n = strlen(pattern); // 模式串长度// 构造前缀表int *next = (int *)malloc(sizeof(int) * n);computePrefixTable(pattern, next, n);int i = 0; // 主串索引int j = 0; // 模式串索引while (i < m) {if (text[i] == pattern[j]) {i++;j++;}if (j == n) {free(next);return i - j; // 匹配成功,返回匹配起始位置} else if (i < m && text[i] != pattern[j]) {if (j > 0) {j = next[j - 1]; // 利用前缀表回溯} else {i++;}}}free(next);return -1; // 未找到匹配
}
测试代码

以下是完整测试代码,展示了如何使用 KMP 算法进行模式匹配:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>// 计算模式串的前缀表 (next 数组)
void computePrefixTable(const char *pattern, int *next, int n) {next[0] = 0; // 第一个字符的前缀长度总是 0int len = 0; // 当前最长前缀的长度int i = 1;while (i < n) {if (pattern[i] == pattern[len]) {len++;next[i] = len;i++;} else {if (len > 0) {len = next[len - 1]; // 回溯到上一个最长前缀的位置} else {next[i] = 0;i++;}}}
}// KMP 模式匹配
int KMP(const char *text, const char *pattern) {int m = strlen(text);    // 主串长度int n = strlen(pattern); // 模式串长度// 构造前缀表int *next = (int *)malloc(sizeof(int) * n);computePrefixTable(pattern, next, n);int i = 0; // 主串索引int j = 0; // 模式串索引while (i < m) {if (text[i] == pattern[j]) {i++;j++;}if (j == n) {free(next);return i - j; // 匹配成功,返回匹配起始位置} else if (i < m && text[i] != pattern[j]) {if (j > 0) {j = next[j - 1]; // 利用前缀表回溯} else {i++;}}}free(next);return -1; // 未找到匹配
}int main() {const char *text = "ababcabcacbab";    // 主串const char *pattern = "abcac";        // 模式串int pos = KMP(text, pattern);if (pos != -1) {printf("模式串在主串中的起始位置为: %d\n", pos); // 输出: 5} else {printf("模式串未找到!\n");}return 0;
}
3.2.2 插入子串

在指定位置插入一个字符串。

// 插入子串
void insertstring(LPSTR pstr, const char *str, int pos) {int len = strlen(str);if (pos < 0 || pos > pstr->curSize || pstr->curSize + len >= 1024) {printf("插入失败:无效下标或字符串过长!\n");return;}// 移动原有字符腾出空间for (int i = pstr->curSize - 1; i >= pos; i--) {pstr->mem[i + len] = pstr->mem[i];}// 插入新字符串for (int i = 0; i < len; i++) {pstr->mem[pos + i] = str[i];}pstr->curSize += len;
}
3.2.3 删除子串

区间删除:直接删除指定范围的字符。

// 删除子串
void deletestring(LPSTR pstr, int start, int end) {if (start < 0 || end >= pstr->curSize || start > end) {printf("删除失败:区间不合法!\n");return;}int count = end - start + 1;// 后续字符前移for (int i = start; i < pstr->curSize - count; i++) {pstr->mem[i] = pstr->mem[i + count];}pstr->curSize -= count;// 清除多余字符for (int i = pstr->curSize; i < pstr->curSize + count; i++) {pstr->mem[i] = '\0';}
}

匹配删除:删除与某个模式串匹配的部分。

匹配删除操作需要先找到模式串在主串中的位置,然后将其删除。

  1. 使用子串查找算法(如 BF 算法)确定模式串的位置。
  2. 如果找到模式串,调用区间删除函数 deletestring 删除该部分内容。
// 查找子串位置 - BF算法
int findsubstringBF(LPSTR mainStr, const char *pattern) {int m = mainStr->curSize; // 主串长度int n = strlen(pattern);  // 模式串长度for (int i = 0; i <= m - n; i++) {int j = 0;while (j < n && mainStr->mem[i + j] == pattern[j]) {j++;}if (j == n) {return i; // 返回匹配的起始位置}}return -1; // 未找到
}// 匹配删除
void matchdelete(LPSTR pstr, const char *pattern) {int start = findsubstringBF(pstr, pattern);  // 找到模式串的起始位置if (start == -1) {printf("未找到模式串,无法删除!\n");return;}int end = start + strlen(pattern) - 1;  // 计算模式串的结束位置// 调用区间删除函数deletestring(pstr, start, end);
}
3.3.4 替换子串

将子串替换为新的内容。

// 替换子串
void replacestring(LPSTR pstr, const char *oldStr, const char *newStr) {int pos = findsubstringBF(pstr, oldStr);if (pos == -1) {printf("子串未找到,无法替换!\n");return;}// 删除旧子串deletestring(pstr, pos, pos + strlen(oldStr) - 1);// 插入新子串insertstring(pstr, newStr, pos);
}

4. 串的存储实现与代码示例

以下代码展示了基于顺序存储的一些基本串操作的实现,包括创建串、插入操作、区间删除等:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>// 定义字符串数据结构
typedef struct {char mem[1024]; // 用于存储字符的数组int curSize;    // 当前字符串长度
} String, *LPSTR;// 创建字符串
LPSTR createstring(const char *str) {LPSTR pstr = (LPSTR)malloc(sizeof(String));assert(pstr);memset(pstr->mem, '\0', 1024); // 初始化数组int count = 0;while (str[count] != '\0' && count < 1024) {pstr->mem[count] = str[count];count++;}pstr->curSize = count; // 更新当前长度return pstr;
}// 打印字符串
void printstring(LPSTR pstr) {for (int i = 0; i < pstr->curSize; i++) {putchar(pstr->mem[i]);}putchar('\n');
}// 求串长度
int getlength(LPSTR pstr) {return pstr->curSize;
}// 串连接
void concatstring(LPSTR dest, const char *src) {int srcLen = strlen(src);if (dest->curSize + srcLen >= 1024) {printf("字符串过长,无法连接!\n");return;}for (int i = 0; i < srcLen; i++) {dest->mem[dest->curSize + i] = src[i];}dest->curSize += srcLen;
}// 串比较
int comparestring(LPSTR str1, LPSTR str2) {return strcmp(str1->mem, str2->mem);
}// 串拷贝
void copystring(LPSTR dest, LPSTR src) {memset(dest->mem, '\0', 1024); // 清空目标串for (int i = 0; i < src->curSize; i++) {dest->mem[i] = src->mem[i];}dest->curSize = src->curSize;
}// 查找子串 - BF算法
int findsubstringBF(LPSTR mainStr, const char *pattern) {int m = mainStr->curSize; // 主串长度int n = strlen(pattern);  // 模式串长度for (int i = 0; i <= m - n; i++) {int j = 0;while (j < n && mainStr->mem[i + j] == pattern[j]) {j++;}if (j == n) {return i; // 返回匹配的起始位置}}return -1; // 未找到
}// 插入子串
void insertstring(LPSTR pstr, const char *str, int pos) {int len = strlen(str);if (pos < 0 || pos > pstr->curSize || pstr->curSize + len >= 1024) {printf("插入失败:无效下标或字符串过长!\n");return;}// 移动原有字符腾出空间for (int i = pstr->curSize - 1; i >= pos; i--) {pstr->mem[i + len] = pstr->mem[i];}// 插入新字符串for (int i = 0; i < len; i++) {pstr->mem[pos + i] = str[i];}pstr->curSize += len;
}// 删除子串
void deletestring(LPSTR pstr, int start, int end) {if (start < 0 || end >= pstr->curSize || start > end) {printf("删除失败:区间不合法!\n");return;}int count = end - start + 1;// 后续字符前移for (int i = start; i < pstr->curSize - count; i++) {pstr->mem[i] = pstr->mem[i + count];}pstr->curSize -= count;// 清除多余字符for (int i = pstr->curSize; i < pstr->curSize + count; i++) {pstr->mem[i] = '\0';}
}// 替换子串
void replacestring(LPSTR pstr, const char *oldStr, const char *newStr) {int pos = findsubstringBF(pstr, oldStr);if (pos == -1) {printf("子串未找到,无法替换!\n");return;}// 删除旧子串deletestring(pstr, pos, pos + strlen(oldStr) - 1);// 插入新子串insertstring(pstr, newStr, pos);
}// 主函数测试
int main() {// 创建字符串LPSTR str1 = createstring("Hello World");printf("原始字符串: ");printstring(str1);// 求字符串长度printf("字符串长度: %d\n", getlength(str1));// 串连接concatstring(str1, "!!!");printf("连接后的字符串: ");printstring(str1);// 插入子串insertstring(str1, " Beautiful", 5);printf("插入后的字符串: ");printstring(str1);// 删除子串deletestring(str1, 6, 15);printf("删除后的字符串: ");printstring(str1);// 替换子串replacestring(str1, "World", "Universe");printf("替换后的字符串: ");printstring(str1);// 查找子串int pos = findsubstringBF(str1, "Universe");if (pos != -1) {printf("子串 'Universe' 的起始位置: %d\n", pos);} else {printf("子串 'Universe' 未找到!\n");}// 串拷贝LPSTR str2 = createstring("");copystring(str2, str1);printf("拷贝后的字符串: ");printstring(str2);// 串比较const char *compareResult = comparestring(str1, str2) == 0 ? "相等" : "不相等";printf("str1 和 str2 比较结果: %s\n", compareResult);// 释放内存free(str1);free(str2);return 0;
}

5. 串的实际应用

  1. 文本编辑器:字符串的插入、删除、查找、替换等操作。
  2. 网络传输:处理传输的数据包和协议,例如 HTTP 报文。
  3. 搜索引擎:关键词匹配、统计、自动补全等。
  4. DNA 序列分析:基因比对、模式匹配。
  5. 文件路径解析:操作系统中对文件路径的处理。
  6. 正则表达式:复杂模式查找与替换。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/65870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

生成式AI与RAG架构:如何选择合适的向量数据库?

大规模语言模型和情境感知的AI应用程序推动了检索增强生成&#xff08;RAG&#xff09;架构的发展&#xff0c;使其成为关注的焦点。RAG将生成模型的力量与外部知识相结合&#xff0c;允许系统生成更加具体且与情境相关的回应。 向量数据库构成了RAG系统的基石。选择正确的向量…

hive on spark报错解决(基于hive-3.1.3和spark-2.3.0)

相关配置可参考&#xff1a;https://blog.csdn.net/weixin_46389691/article/details/134126254 原作者&#xff1a;月亮给我抄代码 他写的很详细 ERROR : Job failed with java.lang.IllegalAccessError: tried to access method com.google.common.base.Stopwatch.<init&…

电脑找不到mfc110.dll文件要如何解决?Windows缺失mfc110.dll文件快速解决方法

一、mfc110.dll文件的重要性 mfc110.dll&#xff0c;全称Microsoft Foundation Class Library 110&#xff0c;是Microsoft Visual C Redistributable for Visual Studio 2012的一部分。这个动态链接库&#xff08;DLL&#xff09;文件对于支持基于MFC&#xff08;Microsoft F…

大模型Weekly 03|OpenAI o3发布;DeepSeek-V3上线即开源!

大模型Weekly 03&#xff5c;OpenAI o3发布&#xff1b;DeepSeek-V3上线即开源&#xff01;DeepSeek-V3上线即开源&#xff1b;OpenAI 发布高级推理模型 o3https://mp.weixin.qq.com/s/9qU_zzIv9ibFdJZ5cTocOw?token47960959&langzh_CN 「青稞大模型Weekly」&#xff0c;持…

4、上一个接口返回值,作为下一个方法(接口)的变量

import requestsclass TestCase:# 设置1个类变量B "初始值"def test1(self):url "**这里是接口url**"params {"type": "json"}resp1 requests.get(urlurl, paramsparams)# .json()用于将服务器返回的 JSON 格式的响应内容解析为 P…

USB 中断传输的 PID 序列

中断传输的 PID 序列 端点在初始化后&#xff0c;从 DATA0 开始&#xff0c;每成功执行一个事务&#xff0c;数据包序列翻转一次&#xff08;从 DATA0 变为DATA1 或从 DATA1 变为 DATA0)。 数据翻转和传输的个数没有直接关系&#xff0c;只由端点在初始化后处理的总数决定。 …

SAP财务凭证的更改、冲销的方式

文章目录 一、财务凭证更改二、财务凭证冲销 【SAP系统研究】 #SAP #FICO #SAP财务 一、财务凭证更改 &#xff08;1&#xff09;已经过账的财务凭证 FB02&#xff1a;过完帐的允许更改的地方有限&#xff0c;只有凭证抬头文本、参照、分配、文本、原因代码等。 &#xff0…

OpenCV的人脸检测模型FaceDetectorYN

OpenCV的人脸检测模型FaceDetectorYN 1. 官网地址2. 如何使用2.1.到opencv_zoo下载模型文件和代码2.2. 下载文件展示2.3. 修改了demo支持读取视频文件&#xff0c;默认是图片和摄像头## 2.4 效果展示 1. 官网地址 https://docs.opencv.org/4.x/df/d20/classcv_1_1FaceDetector…

服务端错误的处理和web安全检测

文章目录 I 服务端错误的处理业务返回码处理前端处理业务返回码nginx处理http状态码II web安全检测区分服务器类型主机扫漏III 使用 micro_httpd 搭建一个PHP站点步骤下载micro_httpd 并安装它配置micro_httpd 来服务PHP文件I 服务端错误的处理 服务端发生错误时,返回给前端的…

vue使用el-select下拉框自定义复选框

在 Vue 开发中&#xff0c;高效且美观的组件能极大地提升用户体验和开发效率。在vue中使用elementplus 的 el-select下拉框实现了一个自定义的多选下拉框组件。 一、代码功能概述 这段代码创建了一个可多选的下拉框组件&#xff0c;通过el-select和el-checkbox-group结合的方…

Elasticsearch DSL版

文章目录 1.索引库操作创建索引库&#xff1a;删除索引库&#xff1a;查询索引库&#xff1a;修改索引库&#xff1a;总结 2.文档操作创建文档&#xff1a;查询文档&#xff1a;删除文档&#xff1a;全量修改文档&#xff1a;增量修改文档&#xff1a;总结 3.DSL查询语法&#…

Python性能分析深度解析:从`cProfile`到`line_profiler`的优化之路

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在软件开发过程中,性能优化是提升应用质量和用户体验的关键环节。Python作为广泛应用的高级编程语言,其性能分析工具为开发者提供了强大的…

01-英语准备

首先是自我介绍&#xff0c;中英文都可以&#xff0c;建议提前打好草稿然后开始背&#xff0c;模板网上有很多&#xff0c;可以自行查找&#xff0c;主要就是个人的一些基本情况&#xff0c;竞赛获奖经历&#xff0c;感兴趣的方向等等。接下来就是老师问的一些问题了。 做个英文…

亚信科技研发智能化实践之路

作者&#xff1a;亚信科技高级研发经理史伟星 亚信科技是一家专注于 To B 业务的公司。公司 1993 年成立&#xff0c;于 2000 年成为纳斯达克首批上市的高科技企业。2010 年&#xff0c;通过持续深耕&#xff0c;成为中国领先的通信软件产品服务商。2014 年&#xff0c;完成私…

==和===的区别,被坑的一天

在 JavaScript 中&#xff0c; 和 都用于比较两个值&#xff0c;但它们有一个重要的区别&#xff1a; 1. (宽松相等运算符) 进行比较时&#xff0c;会 自动类型转换&#xff08;也叫做强制类型转换&#xff09;&#xff0c;即如果比较的两个值的类型不同&#xff0c;JavaScr…

如何不修改模型参数来强化大语言模型 (LLM) 能力?

前言 如果你对这篇文章感兴趣&#xff0c;可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」&#xff0c;查看完整博客分类与对应链接。 大语言模型 (Large Language Model, LLM, e.g. ChatGPT) 的参数量少则几十亿&#xff0c;多则上千亿&#xff0c;对其的训…

使用Python和OpenCV进行视觉图像分割

简介&#x1f381; 在图像处理领域&#xff0c;图像分割是一项基础且关键的技术&#xff0c;它涉及到将图像划分为若干个具有特定属性的区域。本文将通过一个实践项目&#xff0c;展示如何使用Python编程语言&#xff0c;结合OpenCV库&#xff0c;对一张玫瑰花的图片进行图像分…

Adobe ColdFusion 关键安全漏洞紧急修复

随着网络攻击的日益严重&#xff0c;网络安全问题逐渐引起全球的广泛关注。Adobe 最近发布的一项紧急补丁为其 ColdFusion 平台解决了一个关键安全漏洞。这一漏洞以 CVE-2024-53961 标识&#xff0c;经过评估后被赋予了 7.4 的 CVSS 基分数&#xff0c;形势不容小觑。尤其值得一…

代码解析:安卓VHAL的AIDL参考实现

以下内容基于安卓14的VHAL代码。 总体架构 参考实现采用双层架构。上层是 DefaultVehicleHal&#xff0c;实现了 VHAL AIDL 接口&#xff0c;并提供适用于所有硬件设备的通用 VHAL 逻辑。下层是 FakeVehicleHardware&#xff0c;实现了 IVehicleHardware 接口。此类可模拟与实…

vLLM结构化输出(Guided Decoding)

简介 vLLM 的结构化输出特性是通过“引导式解码”&#xff08;Guided Decoding&#xff09;实现的&#xff0c;这一功能允许模型在生成文本时遵循特定的格式约束&#xff0c;例如 JSON 模式或正则表达式&#xff0c;从而确保生成的内容符合预期的结构化要求。 后端引擎 启动…