【APK安全】组件安全核心风险与防御指南 - 详解

news/2025/10/1 11:21:42/文章来源:https://www.cnblogs.com/ljbguanli/p/19122250

【APK安全】组件安全核心风险与防御指南 - 详解

文章目录

    • 前言
    • 一、APK组件安全的核心风险
      • 1. 风险1:Intent Scheme URL检测缺失(恶意调用与数据窃取)
        • 风险本质
        • 典型攻击案例:Scheme劫持窃取用户信息
      • 2. 风险2:OpenFileInput权限与校验疏漏(私有文件泄露)
        • 风险本质
        • 漏洞场景:未校验文件完整性导致数据篡改
      • 3. 风险3:OpenOrCreateDatabase安全缺陷(数据库明文泄露)
        • 风险本质
        • 防御缺失案例:未加密数据库被窃取账户信息
      • 4. 风险4:SharePreference劫持(敏感配置泄露)
        • 风险本质
        • 典型疏漏:危险模式导致Token被盗
    • 二、组件安全防御方案
      • 1. Intent Scheme URL检测强化
        • 核心措施
        • 安全实现代码
      • 2. OpenFileInput安全管控
        • 核心措施
        • 适配代码
      • 3. OpenOrCreateDatabase加密与权限防护
        • 核心措施
        • 加密实现代码
      • 4. SharePreference劫持防御
        • 核心措施
        • 合规配置代码
    • 三、组件安全测试方法
      • 1. 静态测试(代码与配置审核)
      • 2. 动态测试(漏洞利用模拟)
    • 四、总结:组件安全的核心原则

⚠️本博文所涉安全渗透测试技术、方法及案例,仅用于网络安全技术研究与合规性交流,旨在提升读者的安全防护意识与技术能力。任何个人或组织在使用相关内容前,必须获得目标网络 / 系统所有者的明确且书面授权,严禁用于未经授权的网络探测、漏洞利用、数据获取等非法行为。

前言

Android系统通过“组件化通信”实现APP内部及跨APP功能调用,核心组件(如Activity、Service、ContentProvider)及数据存储相关API(如OpenFileInput、SharePreference)是APK运行的基础。但若组件配置或API使用存在疏漏(如Intent Scheme未校验URL、数据库明文存储),攻击者可利用这些缺陷实施数据窃取、恶意调用、内容篡改等攻击——例如通过伪造Intent获取用户隐私,或读取未加密的数据库文件窃取账户信息。

随着Android 15(API 35)对组件权限管控的进一步强化(如严格限制跨APP文件访问、废弃危险存储模式),开发者需重点关注四大核心风险点,从“输入校验、权限控制、数据加密”三方面构建组件安全防线。本文将拆解风险场景、提供适配方案及测试方法,助力APK抵御组件级攻击。

一、APK组件安全的核心风险

Android组件安全依赖“权限控制→输入校验→数据保护”三层防护,任一环节缺失均会引发漏洞。以下结合实际攻击案例,解析四大核心风险:

1. 风险1:Intent Scheme URL检测缺失(恶意调用与数据窃取)

风险本质

Intent Scheme是APP通过自定义URL协议(如myapp://)接收外部调用的机制,常用于唤起特定功能(如从网页打开APP内页)。若APP未对传入的Scheme URL进行合法性校验(如未校验Host、Path),攻击者可构造恶意URL,通过网页、短信等渠道触发APP组件,实现“窃取敏感数据”或“强制执行危险操作”。

Android 15虽未变更Intent Scheme的基础机制,但强化了“跨APP组件调用的权限校验”——若APP未声明android:exported="true"却接收外部Intent,系统会直接拦截;但已导出的组件若存在URL检测缺失,仍会面临攻击风险。

典型攻击案例:Scheme劫持窃取用户信息

某电商APP为实现“网页唤起订单页”功能,在AndroidManifest中注册了支持Scheme的Activity,并未校验传入URL:

<!-- 风险配置:导出Activity支持Scheme,但未限制URL来源 --><activityandroid:name=".OrderActivity"android:exported="true"><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><dataandroid:scheme="myapp"android:host="*" /> <!-- 允许任意Host调用 --></intent-filter></activity>
// 风险代码:未校验Scheme URL合法性,直接提取参数
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
Uri data = intent.getData();
// 直接读取用户ID参数,未校验Host是否为可信域名
String userId = data.getQueryParameter("user_id");
// 根据userId获取用户订单信息并展示
loadOrderInfo(userId);
}
}

攻击者通过以下步骤实施攻击:

  1. 构造恶意URL:myapp://malicious.com?user_id=10086(伪造可信用户ID);
  2. 制作包含该URL的钓鱼网页(如通过短信发送链接),诱导用户点击;
  3. 用户点击后,系统唤起电商APP的OrderActivity;
  4. APP未校验URL的Host(malicious.com非官方域名),直接根据伪造的user_id加载订单信息;
  5. 攻击者通过网页后台记录APP返回的订单数据(如商品明细、收货地址),实现信息窃取。

2. 风险2:OpenFileInput权限与校验疏漏(私有文件泄露)

风险本质

OpenFileInput是Android提供的读取APP内部私有文件(存储于/data/data/<包名>/files/)的API,默认仅APP自身可访问。但存在两类风险:

Android 15已完全屏蔽MODE_WORLD_READABLE/MODE_WORLD_WRITEABLE,强制私有文件仅APP自身可访问,但“文件内容校验缺失”的风险仍普遍存在。

漏洞场景:未校验文件完整性导致数据篡改

某医疗APP使用OpenFileInput读取存储患者病历的私有文件,未校验文件是否被篡改:

// 风险代码:读取私有文件时未校验完整性
private String readMedicalRecord() {
String record = "";
try {
// 打开私有文件(权限为默认的MODE_PRIVATE)
FileInputStream fis = openFileInput("patient_record.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String line;
while ((line = br.readLine()) != null) {
record += line;
}
br.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
// 直接返回文件内容,未校验是否被篡改
return record;
}

攻击者通过root设备实施攻击:

  1. 利用root权限进入APP的私有文件目录(/data/data/com.example.medical/files/);
  2. 篡改patient_record.txt中的“用药剂量”字段(如将“5mg”改为“50mg”);
  3. APP下次启动时,通过OpenFileInput读取篡改后的文件,展示错误用药信息;
  4. 医生依据错误信息开具处方,引发医疗风险。

3. 风险3:OpenOrCreateDatabase安全缺陷(数据库明文泄露)

风险本质

OpenOrCreateDatabase用于创建或打开APP私有数据库(存储于/data/data/<包名>/databases/),默认采用明文存储。若存在以下缺陷,会导致敏感数据泄露:

Android 15虽强化了数据库文件的权限管控,但未默认提供加密功能,需开发者手动集成加密方案(如SQLCipher)。

防御缺失案例:未加密数据库被窃取账户信息

某金融APP使用OpenOrCreateDatabase创建数据库存储用户账户信息,未加密且未限制权限:

// 风险代码:明文创建数据库,未加密且使用危险模式
private void createAccountDatabase() {
// MODE_WORLD_READABLE已废弃,但旧代码仍可能使用
SQLiteDatabase db = openOrCreateDatabase(
"account.db",
Context.MODE_PRIVATE, // 虽为私有,但未加密
null
);
// 创建表存储用户名、密码(明文)
db.execSQL("CREATE TABLE IF NOT EXISTS user (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"username TEXT," +
"password TEXT)");
db.close();
}

攻击者通过以下步骤窃取数据:

  1. 在root设备上,通过ADB命令拉取数据库文件:adb pull /data/data/com.example.finance/databases/account.db
  2. 使用SQLite可视化工具(如SQLiteStudio)打开account.db
  3. 直接读取user表中的明文用户名和密码;
  4. 利用窃取的 credentials 登录用户账户,转移资产。

4. 风险4:SharePreference劫持(敏感配置泄露)

风险本质

SharePreference是APP存储轻量级配置(如登录Token、用户设置)的常用组件,默认存储于/data/data/<包名>/shared_prefs/的XML文件中。风险主要源于两点:

Android 15已禁止危险模式,但“敏感数据明文存储”仍是高发风险——据安全测试统计,约30%的APP仍在SharePreference中明文存储登录Token。

典型疏漏:危险模式导致Token被盗

某社交APP为兼容旧设备,使用MODE_WORLD_READABLE创建SharePreference存储登录Token:

// 风险代码:使用危险模式存储敏感Token
private void saveLoginToken(String token) {
SharedPreferences sp = getSharedPreferences(
"user_config",
Context.MODE_WORLD_READABLE // 允许其他APP读取
);
SharedPreferences.Editor editor = sp.edit();
editor.putString("login_token", token); // 明文存储Token
editor.apply();
}

恶意APP通过以下步骤劫持Token:

  1. 在AndroidManifest中声明“访问其他APP私有文件”的权限(旧系统可绕过);

  2. 通过createPackageContext获取社交APP的上下文:

    Context targetContext = createPackageContext(
    "com.example.social",
    Context.CONTEXT_IGNORE_SECURITY // 忽略权限校验(旧系统漏洞)
    );
  3. 读取社交APP的SharePreference:

    SharedPreferences sp = targetContext.getSharedPreferences("user_config", Context.MODE_WORLD_READABLE);
    String token = sp.getString("login_token", "");
  4. 使用窃取的Token调用社交APP的API,伪造用户登录,发送钓鱼消息或窃取好友列表。

二、组件安全防御方案

针对上述四大风险,需从“输入校验、权限控制、数据加密、版本适配”四维度制定防御措施,结合Android 15特性实现合规安全。

1. Intent Scheme URL检测强化

核心措施
  • 限制Scheme的可信Host/Path:在AndroidManifest中明确指定允许的Host(避免*),或在代码中校验URL的Host是否在白名单内;
  • 校验Intent来源:通过intent.getPackage()判断调用者是否为可信APP,非可信来源直接拦截;
  • 避免导出非必要组件:仅对需外部调用的Activity设置android:exported="true",其他组件默认false
安全实现代码
  1. Manifest配置(限制Host):

    <activityandroid:name=".OrderActivity"android:exported="true">
    <intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><dataandroid:scheme="myapp"android:host="official.example.com" /> <!-- 仅允许官方Host --></intent-filter>
    </activity>
  2. 代码校验(白名单+来源校验):

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Intent intent = getIntent();
    if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
    Uri data = intent.getData();
    if (data == null) {
    finish(); // 无URL直接退出
    return;
    }
    // 校验Host是否在白名单
    String host = data.getHost();
    List<String> trustedHosts = Arrays.asList("official.example.com");if (!trustedHosts.contains(host)) {Log.e("SchemeSecurity", "非法Host:" + host);finish();return;}// 校验调用者是否为可信APP(可选,针对高敏感功能)String callerPackage = intent.getPackage();List<String> trustedApps = Arrays.asList("com.example.webview");if (callerPackage == null || !trustedApps.contains(callerPackage)) {Log.e("SchemeSecurity", "非法调用者:" + callerPackage);finish();return;}// 安全提取参数String userId = data.getQueryParameter("user_id");loadOrderInfo(userId);}}

2. OpenFileInput安全管控

核心措施
适配代码
  1. 文件完整性校验(SHA-256):

    // 生成文件哈希值(存储文件时调用)
    private String getFileHash(File file) throws NoSuchAlgorithmException, IOException {
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    FileInputStream fis = new FileInputStream(file);
    byte[] buffer = new byte[1024];
    int len;
    while ((len = fis.read(buffer)) != -1) {
    digest.update(buffer, 0, len);
    }
    fis.close();
    // 转换为十六进制字符串
    BigInteger bigInt = new BigInteger(1, digest.digest());
    return bigInt.toString(16);
    }
    // 读取文件时校验完整性
    private String readMedicalRecord() {
    String record = "";
    File recordFile = new File(getFilesDir(), "patient_record.txt");
    // 从安全存储(如加密SharedPreference)获取预存的哈希值
    String trustedHash = getEncryptedPrefs().getString("record_hash", "");
    try {
    // 校验当前文件哈希与预存哈希是否一致
    String currentHash = getFileHash(recordFile);
    if (!currentHash.equals(trustedHash)) {
    Log.e("FileSecurity", "文件已被篡改!");
    return record; // 返回空数据,避免加载篡改内容
    }
    // 校验通过,读取文件(若加密需先解密)
    FileInputStream fis = openFileInput("patient_record.txt");
    BufferedReader br = new BufferedReader(new InputStreamReader(fis));
    String line;
    while ((line = br.readLine()) != null) {
    record += line;
    }
    br.close();
    fis.close();
    } catch (Exception e) {
    e.printStackTrace();
    }
    return record;
    }

3. OpenOrCreateDatabase加密与权限防护

核心措施
加密实现代码
  1. 集成SQLCipher(build.gradle依赖):

    dependencies {implementation 'net.zetetic:android-database-sqlcipher:4.5.4'
    }
  2. 加密创建数据库:

    import net.sqlcipher.database.SQLiteDatabase;
    import net.sqlcipher.database.SQLiteOpenHelper;
    public class EncryptedDbHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "account.db";
    private static final int DB_VERSION = 1;
    private static final String ENCRYPT_KEY = "your_secure_key"; // 密钥需安全存储(如设备密钥库)
    public EncryptedDbHelper(Context context) {
    super(context, DB_NAME, null, DB_VERSION);
    // 初始化SQLCipher
    SQLiteDatabase.loadLibs(context);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
    // 创建加密表(存储加密后的密码)
    db.execSQL("CREATE TABLE IF NOT EXISTS user (" +
    "id INTEGER PRIMARY KEY AUTOINCREMENT," +
    "username TEXT," +
    "password TEXT)"); // password字段存储AES加密后的密码
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    // 数据库升级逻辑
    }
    // 打开加密数据库
    public SQLiteDatabase getWritableDatabase() {
    return super.getWritableDatabase(ENCRYPT_KEY);
    }
    public SQLiteDatabase getReadableDatabase() {
    return super.getReadableDatabase(ENCRYPT_KEY);
    }
    }
  3. 密钥安全存储(使用Android KeyStore):避免硬编码密钥,通过KeyStore生成并存储加密密钥。

4. SharePreference劫持防御

核心措施
合规配置代码
  1. 加密存储敏感数据(AES加密):

    // AES加密工具类(简化版)
    public class AesUtils {
    private static final String KEY = "your_aes_key"; // 密钥从KeyStore获取
    public static String encrypt(String content) throws Exception {
    SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "AES");
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.ENCRYPT_MODE, keySpec);
    byte[] encrypted = cipher.doFinal(content.getBytes());
    return Base64.encodeToString(encrypted, Base64.DEFAULT);
    }
    public static String decrypt(String encryptedContent) throws Exception {
    SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), "AES");
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
    cipher.init(Cipher.DECRYPT_MODE, keySpec);
    byte[] decrypted = cipher.doFinal(Base64.decode(encryptedContent, Base64.DEFAULT));
    return new String(decrypted);
    }
    }
    // 安全存储Token
    private void saveLoginToken(String token) {
    try {
    // 加密Token
    String encryptedToken = AesUtils.encrypt(token);
    // 使用MODE_PRIVATE存储
    SharedPreferences sp = getSharedPreferences("user_config", Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sp.edit();
    editor.putString("login_token", encryptedToken);
    editor.apply();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    // 读取Token(解密)
    private String getLoginToken() {
    try {
    SharedPreferences sp = getSharedPreferences("user_config", Context.MODE_PRIVATE);
    String encryptedToken = sp.getString("login_token", "");
    if (TextUtils.isEmpty(encryptedToken)) {
    return "";
    }
    // 解密Token
    return AesUtils.decrypt(encryptedToken);
    } catch (Exception e) {
    e.printStackTrace();
    return "";
    }
    }

三、组件安全测试方法

组件安全需通过“静态代码审核+动态漏洞验证”双重测试,确保防御措施落地。重点测试以下内容:

1. 静态测试(代码与配置审核)

2. 动态测试(漏洞利用模拟)

  • Intent Scheme攻击模拟
    1. 使用ADB发送恶意Intent:adb shell am start -a android.intent.action.VIEW -d "myapp://malicious.com?user_id=10086" com.example.app
    2. 观察APP是否拦截该请求,或是否返回敏感数据;
  • 文件与数据库窃取
    1. 在root设备上,通过adb shell进入APP私有目录(/data/data/<包名>/);
    2. 尝试拉取files/、databases/、shared_prefs/下的文件,检查是否可打开(加密文件应显示乱码);
  • SharePreference劫持模拟
    1. 开发测试APP,尝试通过createPackageContext访问目标APP的SharePreference;
    2. 检查是否能读取到敏感数据(如加密Token应无法解密)。

四、总结:组件安全的核心原则

APK组件安全的本质是“最小权限+全链路防护”,开发者需遵循以下核心原则:

  1. 权限最小化:仅导出必要组件,私有文件/数据库仅授予APP自身访问权限,避免过度开放;
  2. 输入必校验:对Intent Scheme URL、文件路径、数据库查询参数等外部输入,必须通过白名单、哈希校验等方式过滤非法内容;
  3. 敏感必加密:Token、账户信息等敏感数据,优先使用Android KeyStore+加密数据库存储,避免明文或弱加密;
  4. 版本强适配:针对Android 15等新版本的安全特性(如禁用危险存储模式、强化组件权限),及时更新代码,避免依赖废弃API;
  5. 测试常态化:将组件安全测试纳入开发流程,通过静态扫描(如Lint)、动态攻击模拟(如恶意Intent发送)定期验证防御有效性。

组件漏洞往往源于“图方便”的开发习惯(如跳过URL校验、使用明文存储),但攻击者可利用这些微小疏漏实施高危害攻击。唯有从“配置、代码、测试”三方面严格把控,才能筑牢APK的组件安全防线,抵御日益复杂的移动安全威胁。

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

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

相关文章

自己电脑做局域网网站服务器专门做app的公司有哪些

计算机常识 计算机如何存储数据 计算机世界中只有二进制。那么在计算机中存储和运算的所有数据都要转为二进制。包括数字、字符、图片、声音、视频等。 进制 进制也就是进位计数制&#xff0c;是人为定义的带进位的计数方法 实例&#xff1a; // 在java 中 可以使用不同…

中山网站建点东营招标建设信息网

OSPF NSSA实验简述 1、OSPF NSSA区域配置 为解决末端区域维护过大LSDB带来的问题&#xff0c;通过配置stub 区域或totally stub区域可以解决&#xff0c;但是他们都不能引入外部路由场景。 No so stuby area &#xff08;区域&#xff09;NSSA 可以引入外部路由&#xff0c;支持…

书籍网站建设的目的360网站制作潍坊

文章目录1. 题目2. 解题1. 题目 给你一个由正整数组成的数组 nums 。 数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。 例如&#xff0c;序列 [4,6,16] 的最大公约数是 2 。 数组的一个 子序列 本质是一个序列&#xff0c;可以通过删除数组中的某些元素…

长沙做企业网站的公司wordpress加载谷歌

一、梯度消失与爆炸 在神经网络中&#xff0c;梯度消失和梯度爆炸是训练过程中常见的问题。 梯度消失指的是在反向传播过程中&#xff0c;梯度逐渐变小&#xff0c;导致较远处的层对参数的更新影响较小甚至无法更新。这通常发生在深层网络中&#xff0c;特别是使用某些激活函…

gitee 使用安装教程

一、下载方式 1.官网下载https://git-scm.com/downloads 2.淘宝镜像下载https://registry.npmmirror.com/binary.html?path=git-for-windows/2.1安装 1.点击刚刚下载的安装包,然后点击next 2.根据自己的情况选择,一…

2025工业网线厂家权威推荐榜:千兆/拖链/高柔/网线/六类/超五类/6类/超5类/千兆/超六类/8芯/4芯/成品/相机/视觉数据工业网线高强屏蔽与稳定传输实力之选

在工业4.0和智能制造快速发展的今天,工业网络作为数字基础设施的核心组成部分,其稳定性与可靠性直接关系到生产系统的运行效率。工业网线作为网络传输的物理载体,不仅需要具备优异的信号传输性能,更要能在恶劣的工…

VisualMimic——基于视觉的人形行走-操作控制:低层策略负责平衡控制且跟踪高层下发的指令、高层策略则基于自我中心视觉输入生成任务跟踪指令 - 实践

VisualMimic——基于视觉的人形行走-操作控制:低层策略负责平衡控制且跟踪高层下发的指令、高层策略则基于自我中心视觉输入生成任务跟踪指令 - 实践pre { white-space: pre !important; word-wrap: normal !importan…

g4560做网站服务器网络舆情的应对及处理

用两个栈实现一个队列。队列的声明如下&#xff0c;请实现它的两个函数 appendTail 和 deleteHead &#xff0c;分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素&#xff0c;deleteHead 操作返回 -1 ) 示例 1&#xff1a; 输入&#xff1a; ["…

套用模板网站哪里有做网站培训的

题目 不使用任何内建的哈希表库设计一个哈希映射&#xff08;HashMap&#xff09;。 实现 MyHashMap 类&#xff1a; MyHashMap() 用空映射初始化对象 void put(int key, int value) 向 HashMap 插入一个键值对 (key, value) 。如果 key 已经存在于映射中&#xff0c;则更新…

FPGA强化-简易频率计 - 实践

FPGA强化-简易频率计 - 实践2025-10-01 11:01 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important;…

基本分页存储管理的基本概念

将内存分为一个个大小相等的分区,每个分区就是一个页框(页框=页帧=内存块=物理快=物理页面)每一个页框都有一个编号--页框号,页框号从0开始。 将进程的逻辑地址空间也分为与页框大小相等的一个个部分,每个部分称为…

无锡网站制作哪里有国家高新技术企业申报时间

最近在做docker容器的时候遇到了问题&#xff0c;安装的GD库没有JPEG支持&#xff0c;因为项目用到了绘图技术&#xff0c;这个支持必不可少。要解决这个问题也很简单&#xff1a; 安装jpeg支持&#xff0c;重新编译gd库&#xff0c;生成gd.so文件&#xff0c;重新加载gd库扩展…

设计企业的网站个人网页设计硬件需求

Spectral Python (SPy) 是一个纯 Python 模块&#xff0c;用于处理高光谱图像数据。它具有读取、显示、操作和分类高光谱图像的功能。 SPy 需要 Python 并依赖于其他几个免费提供的 Python 模块。在安装 SPy 之前&#xff0c;您应该确保满足其依赖项。虽然您可以仅使用 Python…

luogu P6503 [COCI 2010/2011 #3] DIFERENCIJA

题目大意 题面 让我们求一个序列中的 \[\sum^{n}_{i=1}\sum^{n}_{j=i}(\max_{i\leq k\leq j} a_k-\min_{i\leq k \leq j} a_k) \]Sol 由于暴力是\(O(n^2)\)的,所以我们需要优化 我们先看暴力的流程:每次选取一段区间求…

做网站一个月能挣多少钱洛阳做网站哪家便宜

1. 适配器模式 (Adapter Pattern) 适配器模式是一种结构型设计模式&#xff0c;旨在将一个类的接口转换成客户端所期待的另一个接口&#xff0c;从而使原本由于接口不兼容而无法一起工作的类能够协同工作。适配器模式通常用于需要复用现有类但其接口与要求不匹配的情况。 1.1…

网络公司网站建设服务dw软件免费安装

候选基因如何分析&#xff1f; 通常情况下关联分析会得到一大堆候选基因&#xff0c;总不可能每个都有用&#xff0c;因此需要对候选基因进行深一步分析&#xff0c;本篇笔记分享一下群体遗传学研究中GWAS候选位点与候选基因的筛选思路。主要的方式包括单基因关联分析、连锁程度…

2025宅基地纠纷律所权威推荐榜:专业调解与胜诉保障实力之选

宅基地纠纷作为农村土地争议的重要类型,近年来呈现持续增长态势。随着城乡一体化进程加速和土地资源价值提升,涉及宅基地使用权确认、边界划分、拆迁补偿等案件数量显著上升。这类纠纷往往牵涉农民切身利益,法律关系…

新化 网站开发比较有特色的网站

多模字符串匹配算法在这里指的是在一个字符串中寻找多个模式字符字串的问题。一般来说&#xff0c;给出一个长字符串和很多短模式字符串&#xff0c;如何最快最省的求出哪些模式字符串出现在长字符串中是我们所要思考的。该算法广泛应用于关键字过滤、入侵检测、病毒检测、分词…

一般做网站宽度是多少深圳的设计网站

LLM-based KG KnowLM OpenSPGKG-based RAG 基本原理 从query出发的语义解析 pre-LLM方法 思想&#xff1a;直接将问题解析为对应的逻辑表达式&#xff0c;然后到知识图谱中查询。 方法&#xff1a;通常包含逻辑表达式、语义解析算法、语义解析模型训练三部分。一般步骤是将问句…