惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official blog

文章列表

DNSMgr——聚合管理所有域名DNS解析+自动续签SSL证书并部署 | AirTouchの小站 雨云香港服务器简单测评 | AirTouchの小站 七牛云 AI 狂送 token 实测到底怎么样 | AirTouchの小站 记一次博客被攻击 | AirTouchの小站 给你的 Artalk 评论区配置验证码和垃圾评论检测 | AirTouchの小站 抓紧上车!免费 E3 开发者账号又来了! | AirTouchの小站 Vercel & Cloudflare Worker 项目推荐(2) | AirTouchの小站 用 Zmail 搭建自己的临时邮箱 | AirTouchの小站 IPv6反解域名?手把手带你搞 | AirTouchの小站 用插件实现 Hexo AI 文章摘要 | AirTouchの小站 用 Librechat 部署自己的 AI 网站 | AirTouchの小站 迁移 Umami Cloud 数据到自建的 Umami | AirTouchの小站 raksmart 圣何塞超低价 vps 测评 | AirTouchの小站 Vercel & Github Actions 项目推荐(1) | AirTouchの小站 macOS Tahoe 26中Electron架构卡顿的临时解决方案 | AirTouchの小站 用Obsidian插件增强Stellar写作体验 | AirTouchの小站 复习一下最小生成树 | AirTouchの小站 2025苹果秋季发布会亮点总结 | AirTouchの小站 分享几个artalk邮件通知模板 | AirTouchの小站 博客的图片应该存哪啊? | AirTouchの小站 Pic Smaller——自部署压缩图片的利器 | AirTouchの小站 企业微信的自定义域名邮箱太香了 | AirTouchの小站 所有道听途说,终获眼见为实 | AirTouchの小站 修复Vercel部署hexo导致文章的更新时间错误 | AirTouchの小站 jsDelivr国内公益加速镜像分享 | AirTouchの小站 搭建自己的busuanzi访问量统计服务 | AirTouchの小站 用Vercel和Netlify反代你的网站 | AirTouchの小站 用EdgeOne配置反向代理 丢掉丑陋的端口号 | AirTouchの小站 拼好鸽香港4区nat机器:月付3.5还要啥自行车! | AirTouchの小站 博客的新域名——xsl.im | AirTouchの小站 如何搭建自己的EdgeOne优选域名 | AirTouchの小站 用EdgeOne加速CloudflareR2存储桶 | AirTouchの小站 EdgeOne自动化上传证书并部署 | AirTouchの小站 你需要把PicGo换成PicList了! | AirTouchの小站 Cursor屏蔽中国大陆?给你解决方案! | AirTouchの小站 使用 Cloudflare Workers 自动获取必应每日壁纸 | AirTouchの小站 题解:P9509『STA - R3』Aulvwc | AirTouchの小站 题解:P11140 [APC001] E - Linear Map | AirTouchの小站 Phira多人联机服务器搭建&使用教程 | AirTouchの小站 腾讯云EdgeOne免费CDN加速你的网站 | AirTouchの小站 Hexo 博客收录指南 | AirTouchの小站 题解:P12646 [KOI 2024 Round 1] 升序 | AirTouchの小站 Cloudflare CDN优选IP加速你的网站 | AirTouchの小站 Giffgaff在线生成esim二维码 | Giffgaff sim转eSIM指南 | AirTouchの小站 RedteaGO - 最划算的大陆漫游 esim 流量卡 | AirTouchの小站 用Alist搭建一个属于自己的网盘系统 | AirTouchの小站 Hexo Stellar 主题装修笔记 | AirTouchの小站 利用CloudflareR2搭建免费图床 | AirTouchの小站 组件样式示例 | AirTouchの小站
题解:P2679 [NOIP2015 提高组] 子串 | AirTouchの小站
AirTouch, me@airtouch.top · 2025-01-17 · via

www.luogu.com.cn

https://www.luogu.com.cn/problem/P2679

老师上课刚讲完这道题,来这里长个估值分享一下,顺便加深记忆。

定义 dp 状态

fi,j,kf_{i,j,k} 表示从字符串 AA 的前 ii 个字符中,取出 kk 个非空子串,拼接后与字符串 BB 的前 jj 个字符相等的方案数。

状态转移

  1. 不取当前字符。
    若第 ii 个字符不属于当前子串,则有 fi,j,k+=fi1,j,kf_{i,j,k}+=f_{i-1,j,k}
  2. 取当前字符, 拼接到新的子串。
    若从位置 ip+1i-p+1ii 的子串等于 Bjp+1:jB_{j-p+1:j} (即子串长度为 pp 且匹配成功),则有 fi,j,k+=fip,jp,k1f_{i,j,k}+=f_{i-p,j-p,k-1}。 

这里 pp 的范围取决于当前 AABB 的匹配情况。

预处理可匹配长度

可以预处理一个二维数组 ycli,jycl_{i,j},表示从 AiA_iBjB_j 开始,最长能匹配的长度,判断 AA 的某段子串与 BB 的某段子串是否匹配。

优化

  1. 接着我们可以发现,每次是修改 fi+1,j+1,k+1f_{i+1,j+1,k+1}fi+p,j+p,k+1f_{i+p,j+p,k+1} 的值,相当于是将一斜行上的值进行修改,所以可以进行差分。
  2. 由于只会从上一状态转移过来,所以可以把 kk 这一维滚掉:
  • fi,jf_{i,j} 表示当前状态。
  • 使用 gi,jg_{i,j} 辅助存储下一状态。
  • 在每次迭代 kk 时,将 ffgg 交换,清空 gg

代码实现

cpp
#include<bits/stdc++.h>
using namespace std;
int n,m,kk,ycl[1010][210],MOD=1000000007;
string a,b;
signed main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    cin>>n>>m>>kk>>a>>b;
    vector<vector<int>> f(n+3,vector<int>(m+3,0));
    vector<vector<int>> g(n+3,vector<int>(m+3,0));
    f[0][0]=1;
    f[1][1]=-1;
    for(int i=0;i<=n;i++){
        for(int j=0;j<=m;j++){
            int t=1;
            while(i+t<=n&&j+t<=m&&a[i+t-1]==b[j+t-1]) t++;
            ycl[i][j]=t-1;
        }
    }
    // for(int i=0;i<=n;i++){
    //     for(int j=0;j<=m;j++){
    //         cout<<ycl[i][j]<<" ";
    //     }
    //     cout<<endl;
    // }
    for(int k=0;k<=kk;k++){
        for(int i=0;i<=n;i++){
            for(int j=0;j<=m;j++){
                int p=ycl[i][j];
                if(i!=0&&j!=0) f[i][j]=(f[i-1][j-1]+f[i][j])%MOD;
                // cout<<i<<" "<<j<<" "<<k<<" "<<f[i][j]<<endl;
                f[i+1][j]=(f[i+1][j]+f[i][j])%MOD;
                f[i+2][j+1]=(f[i+2][j+1]+MOD-f[i][j])%MOD;
                g[i+1][j+1]=(g[i+1][j+1]+f[i][j])%MOD;
                g[i+p+1][j+p+1]=(g[i+p+1][j+p+1]+MOD-f[i][j])%MOD;
            }
        }
        if(k==kk) cout<<f[n][m];
        swap(f,g);
        fill(g.begin(),g.end(),vector<int>(m+3,0));
    }
    return 0;
}