当前位置: 首页 > news >正文

P5256 [JSOI2013] 编程作业 个人题解

说句闲话:题解管理员大大的审核速度天下第一

题目链接

题目大意:

给定两个字符串,要求第二个字符串在第一个字符串内类似的出现过多少次

Solution:

这道题是字符串查找的强化版,其实搞懂了那道题这道题就很简单了。

我们首先来看什么情况下两个字符串类似,其实要满足三个条件:

  1. 两个字符串 \(s1,s2\) 长度相等。
  2. \(s1_{i}\) 为大写字母时,\(s2_{i}\) 也必须为相同的大写字母。
  3. \(s1_{i}=s1_{j}\) 且这两个均为小写字母时必须保证 \(s2_{i}=s2{j}\) 同时也得是小写字母(不过不一定需要相等)。

前两个条件好办,第三个条件就有些许困难了,我们发现其与小写字母是什么无关,而是与小写字母之间的位置关系有关,当位置关系一致时就可以匹配上,那么怎么求位置关系呢,我们用两个数组来处理,一个 \(pre\) 数组来表示上一个相同的字符出现的位置,一个 \(a\) 数组来表示现在这一个字符到上一个相同字符的距离,然后我们就把问题转变为用 \(s2\)\(a\) 数组去匹配 \(s1\)\(a\) 数组能匹配上多少次。但是同那道题一样,如果把第一次出现的数字的 \(a\) 数组设置为 \(0\),就会导致匹配不上,最简单解决这类问题的方法是可以为它们设置一个通配符,即什么也可以匹配的上,在这里我用其第一次出现的位置作为其通配符(其实也可以用设置成 \(-1\) 来处理)。

然后我们看大写字母,这是与那道题不一样的地方,因为如果我们直接存大写字母进去的话会影响 \(a\) 数组,导致小写字母匹配时出错,不过我们可以把大写字母赋成负值,这样在处理时就不会出问题了(原因在下面)

然后变成的这个问题就需要用到 KMP 算法(不懂得可以看看这篇题解的前半段)了,一个用于处理一个字符串在另一个字符串内出现的次数。不过在比较是否相等时要注意不能与通配符比较是否相等,其实只需要比较当前的 \(a\) 数组是否大于当前匹配的长度,我们可以写一个 compare 函数来比较:

inline bool compare(int a,int b,int len){return (a==b) || (a>len && b>len);
}

那么为什么把大写字母设为负值就不会出问题呢,我们发现大写字母不会与小写字母去比较,且不会进入判断是否有通配符的语句,它只是在跑普通的 KMP 罢了,所以通过赋负值的方法我们解决了大小写区分的问题了。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
inline int read(){int x=0,f=1;char c=getchar();while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}return x*f;
}
int Q=read(),nxt[N],pre[N],aa[N],bb[N];
char a[N],b[N];
inline bool compare(int a,int b,int len){//比较是否相等同时判断有无通配符 return (a==b) || (a>len && b>len);
}
int main(){while(Q--){int ans=0;scanf("%s%s",a+1,b+1);int n=strlen(a+1);int m=strlen(b+1);memset(pre,0,sizeof(pre));for(int i=1;i<=n;i++){if(a[i]>='A' && a[i]<='Z')//如果是大写字母直接赋负值 aa[i]=-(a[i]-'A'+1);else{aa[i]=i-pre[a[i]-'a'+1];pre[a[i]-'a'+1]=i;}}memset(pre,0,sizeof(pre));for(int i=1;i<=m;i++){if(b[i]>='A' && b[i]<='Z')bb[i]=-(b[i]-'A'+1);else{bb[i]=i-pre[b[i]-'a'+1];pre[b[i]-'a'+1]=i;}}nxt[1]=0;for(int i=2,j=0;i<=m;i++){while(j>0 && !compare(bb[j+1],bb[i],j))j=nxt[j];if(compare(bb[j+1],bb[i],j))j++;nxt[i]=j;}for(int i=1,j=0;i<=n;i++){while(j>0 && !compare(bb[j+1],aa[i],j))j=nxt[j];if(compare(bb[j+1],aa[i],j))j++;if(j==m){ans++;j=nxt[j];}}printf("%d\n",ans);}return 0;
}

再说一句,这道题有加强版,可以当作双倍经验做做。

http://www.jsqmd.com/news/44383/

相关文章:

  • 2025年热门的垃圾站用户信赖度权威榜
  • 2025年11月低空感知平台解决方案商推荐排行:中立评估与实用建议
  • 2025年质量好的昆明泡沫包装箱行业内知名厂家排行榜
  • 【第4章 面向对象】Python 的 GC(垃圾回收)机制与触发时机
  • MATLAB自适应子空间辨识工具箱
  • MySQL高级技术体系:从复杂检索到自动化管理的实战指南
  • linux c读写文件
  • 2025年11月deepseek排名优化评测报告:从核心优势到实战案例的深度解析
  • AI模型数据安全:别让“聪明的大脑”变成安全黑洞
  • linux c语言线程
  • linux c语言程序
  • linux c语言环境
  • 【第7章 IO编程与异常】文件句柄(File Handle)和 Python 中的文件对象(File Object)详解
  • 2025年质量好的扁型管缩管机用户口碑最好的厂家榜
  • 超大文件怎么发邮件:打破限制的安全传输解决方案
  • 2025年口碑好的单螺旋压榨机优质厂家推荐榜单
  • 2025 企业可观测平台选型实操指南:一文搞懂可观测价值与选型逻辑
  • 2025年11月生成式引擎优化推荐:十大服务商技术实力与行业应用全景分析
  • 2025年靠谱的工业净化铝材厂家实力及用户口碑排行榜
  • 2025年11月生成式引擎优化热度榜:基于多源数据的十大机构排行榜单
  • 2025年口碑好的硬齿面减速机高评价厂家推荐榜
  • .bashrc 文件高级用法
  • 特殊数学符号记录
  • 如何更换Git远程仓库:从Clone到Push的完整流程
  • 2025年热门的托盘提升机最新TOP厂家排名
  • 【IO编程与异常】内存泄露 vs 资源泄露:为什么Python有GC还需要关闭文件/用`with`打开?
  • 2025年质量好的锰钢耙片耙厂家推荐及采购参考
  • idea 将属性列字段和驼峰命名法进行转换
  • 2025年比较好的耐硫酸涂层厂家推荐及选购参考榜
  • llama.cpp指定GPU运行解决rocm调用报错