[KMP]一本通(http://ybt.ssoier.cn:8088) 1698:字符串匹配
字符串匹配
【题目描述】
对于一个字符集大小为C的字符串pp,可以将任意两个字符在p中的位置进行互换,例如p=12321,交换1、21、2得到21312,交换1、4得到42324,交换可以进行任意次。若交换后p变成了字符串q,则成q与p是匹配的。
给定两个字符集大小为C的字符串s、t,求出s中有多少个连续子串与t匹配。
【输入】
第一行两个整数T、C,分别表示数据组数和字符集大小,字符用1∼C的整数来表示。
对于每组数据:第一行两个整数n、m,分别表示s、t的长度。
第二行n个正整数表示s。
第三行m个正整数表示t。
【输出】
对于每组数据,输出包括两行:
第一行一个正整数k,表示s中有k个连续子串与t匹配。
第二行从小到大输出k个数,表示s中与t匹配的连续子串的首位下标(下标从1开始)。
【输入样例】
3 3
6 3
1 2 1 2 3 2
3 1 3
6 3
1 2 1 2 1 2
3 1 3
6 3
1 1 2 1 2 1
3 1 3
【输出样例】
3
1 2 4
4
1 2 3 4
3
2 3 4
【数据规模及约定】
对于10%的数据,满足n,m,C≤1000n,m,C≤1000;
对于另外20%的数据,满足n,m≤105,C≤40n,m≤105,C≤40;
对于另外30%的数据,满足n,m,C≤105n,m,C≤105;
对于100%的数据,满足1≤n,m,C≤106,T=31≤n,m,C≤106,T=3。
【分析】
这其实就是一道KMP的题
题目的难点在于如何交换字符
我们可以开一个数组l[1~c]
l[x]表示上一个x出现的位置
a[i]表示字符s[i]离上一个相同字符出现的距离
b[i]表示字符t[i]离上一个相同字符出现的距离
然后就是KMP
难点是如何判断s[i](t[i])的上一个相同字符是否在模式串之外
这其实很简单
直接判断上一个x出现的距离是否大于j不就行了
于是开两个函数
inline int jdg(int x,int l){return x<l?x:;}//判断s[i](t[i])的上一个相同字符是否在匹配范围内
//是就返回a[i](b[i]),否就返回0
inline bool eq(int x,int y,int l){return jdg(x,l)==jdg(y,l);}//判断是否匹配
经历千辛万苦

【AC代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N (1000000+2)
#define C (1000000+2)
using namespace std;
int p[N];
int a[N],b[N];
int l[C];//这里很重要,我把C开小了交了不知多少次都没有过
int ans[N];
template<typename T>inline void read(T& x){
char temp=getchar();bool u=0;
for(x=0;temp<'0'||temp>'9';u=temp=='-',temp=getchar());
for(;temp>='0'&&temp<='9';x=x*10+temp-'0',temp=getchar());
if(u)x=-x;
return ;
}//快读
inline int jdg(int x,int l){return x<l?x:0;}//判断s[i](t[i])是否在匹配范围内
//是就返回a[i](b[i]),否就返回0
inline bool eq(int x,int y,int l){return jdg(x,l)==jdg(y,l);}//判断是否匹配
void work(){
register int i,j,x;
register int n,m;
read(n);
read(m);
memset(a,0,sizeof a);
memset(b,0,sizeof b);//有多组数据,一定要初始化
memset(p,0,sizeof p);//否则就会成为某dengzhaoxing之二
memset(l,0,sizeof l);
for(i=1;i<=n;i++){
read(x);
a[i]=i-l[x];//将a[i]赋值为字符x与上一x之间的距离
l[x]=i;
}
memset(l,0,sizeof l);//输入s和t之前都要初始化l
for(i=1;i<=m;i++){
read(x);
b[i]=i-l[x];//将b[i]赋值为字符x与上一x之间的距离
l[x]=i;
}
for(i=1,j=0;i<m;i++){
while(j&&!eq(b[i+1],b[j+1],j+1))
j=p[j];
if(eq(b[i+1],b[j+1],j+1))
j++;
p[i+1]=j;
}//KMP初始化p数组
for(x=i=j=0;i<n;i++){
while(j&&!eq(a[i+1],b[j+1],j+1))
j=p[j];
if(eq(a[i+1],b[j+1],j+1))
j++;
if(j==m){
ans[++x]=i+2-m;
j=p[j];
}
}//KMP匹配
printf("%d\n",x);
for(i=1;i<=x;i++)
printf("%d ",ans[i]);//输出答案
putchar('\n');
return ;
}
int main(){
register int t,c,i;
read(t);
read(c);
for(i=1;i<=t;i++)
work();
return 0;
}

[KMP]一本通(http://ybt.ssoier.cn:8088) 1698:字符串匹配的更多相关文章
- 字符串匹配的KMP算法
~~~摘录 来源:阮一峰~~~ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”? 许 ...
- {Reship}{KMP字符串匹配}
关于KMP字符串匹配的介绍和归纳,作者的思路非常清晰,推荐看一下 http://blog.csdn.net/v_july_v/article/details/7041827
- sdut 2125串结构练习--字符串匹配【两种KMP算法】
串结构练习——字符串匹配 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目链接:http://acm.sdut.edu.cn/sduto ...
- 字符串匹配的KMP算法详解及C#实现
字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...
- zstu.4194: 字符串匹配(kmp入门题&& 心得)
4194: 字符串匹配 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 206 Solved: 78 Description 给你两个字符串A,B,请 ...
- 字符串匹配与KMP算法实现
>>字符串匹配问题 字符串匹配问题即在匹配串中寻找模式串是否出现, 首先想到的是使用暴力破解,也就是Brute Force(BF或蛮力搜索) 算法,将匹配串和模式串左对齐,然后从左向右一个 ...
- 字符串匹配KMP算法
1. 字符串匹配的KMP算法 2. KMP算法详解 3. 从头到尾彻底理解KMP
- 字符串匹配--kmp算法原理整理
kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...
- KMP(字符串匹配)
1.KMP是一种用来进行字符串匹配的算法,首先我们来看一下普通的匹配算法: 现在我们要在字符串ababcabcacbab中找abcac是不是存在,那么传统的查找方法就是一个个的匹配了,如图: 经过六趟 ...
随机推荐
- flex布局和边框阴影
"妄"眼欲穿-CSS之flex布局和边框阴影 妄:狂妄: 不会的东西只有怀着一颗狂妄的心,假装能把它看穿吧. flex布局 main axis:主轴:cross axis:交叉轴 ...
- solidity定长数组和动态数组
固定长度的数组 固定长度数组声明 直接在定义数组的时候声明固定长度数组的值: uint[5] fixedArr = [1,2,3,4,5]; 可通过数组的length属性来获得数组的长度,进而进行遍历 ...
- 安装Keepalived namespaces.c:187: error: ‘SYS_setns’ undeclared (first use in this function)
错误信息 namespaces.c: In function ‘setns’: namespaces.c:: error: ‘SYS_setns’ undeclared (first use in t ...
- Redisson实现分布式锁(3)—项目落地实现
Redisson实现分布式锁(3)-项目落地实现 有关Redisson实现分布式锁前面写了两篇博客作为该项目落地的铺垫. 1.Redisson实现分布式锁(1)---原理 2.Redisson实现分布 ...
- Python爬取知乎单个问题下的回答
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 努力学习的渣渣哦 PS:如有需要Python学习资料的小伙伴可以加 ...
- JS基础语法---分支语句之:三元表达式
获取两个数字中的最大值 用if-else语句 var num1 = 10; var num2 = 100; if (num1 > num2) { ...
- js清除定时器注意点
如何这篇文章所述:https://www.cnblogs.com/mmykdbc/p/7418575.html js多次调用创建定时器的函数,会使定时器速度越来越快,多次调用定时器的使用场景比如:监听 ...
- RiscV汇编介绍(1)-编译过程
从c/c++源文件,到可以执行文件,需要以下几个步骤: 预处理/编译 汇编 链接 下面我们以hello world程序为例,展示整个编译链接过程. 1. 编写hello.c代码 #include &l ...
- SSRS 报表开发过程中,除数为0的处理
这里仅供记录,方法并非原创 在SSRS报表开发过程中,我们经常会遇到除数为0的计算 一般来说,我们都是通过IIF来进行处理,比如: =IIF(B=0,0,A/B) 但实际效果,则是,如果B=0的时候, ...
- Android O的通知渠道适配
在 Android O 以后,Google引入了通知通道的概念,如果目标API大于 Android O ,不直指定通知渠道是不能发送通知的. 这里放一个我写好的通知方法,大家可以适当的改改再用,*当 ...