字符串匹配

【题目描述】

对于一个字符集大小为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:字符串匹配的更多相关文章

  1. 字符串匹配的KMP算法

    ~~~摘录 来源:阮一峰~~~ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”? 许 ...

  2. {Reship}{KMP字符串匹配}

    关于KMP字符串匹配的介绍和归纳,作者的思路非常清晰,推荐看一下 http://blog.csdn.net/v_july_v/article/details/7041827

  3. sdut 2125串结构练习--字符串匹配【两种KMP算法】

    串结构练习——字符串匹配 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目链接:http://acm.sdut.edu.cn/sduto ...

  4. 字符串匹配的KMP算法详解及C#实现

    字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...

  5. zstu.4194: 字符串匹配(kmp入门题&& 心得)

    4194: 字符串匹配 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 206  Solved: 78 Description 给你两个字符串A,B,请 ...

  6. 字符串匹配与KMP算法实现

    >>字符串匹配问题 字符串匹配问题即在匹配串中寻找模式串是否出现, 首先想到的是使用暴力破解,也就是Brute Force(BF或蛮力搜索) 算法,将匹配串和模式串左对齐,然后从左向右一个 ...

  7. 字符串匹配KMP算法

    1. 字符串匹配的KMP算法 2. KMP算法详解 3. 从头到尾彻底理解KMP

  8. 字符串匹配--kmp算法原理整理

    kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...

  9. KMP(字符串匹配)

    1.KMP是一种用来进行字符串匹配的算法,首先我们来看一下普通的匹配算法: 现在我们要在字符串ababcabcacbab中找abcac是不是存在,那么传统的查找方法就是一个个的匹配了,如图: 经过六趟 ...

随机推荐

  1. 教妹学 Java:难以驾驭的多线程

    00.故事的起源 “二哥,上一篇<集合>的反响效果怎么样啊?”三妹对她提议的<教妹学 Java>专栏很关心. “这篇文章的浏览量要比第一篇<泛型>好得多.” “这是 ...

  2. 用Java实现二叉查找树

    二叉查找树的实现 1. 原理 二叉查找树,又称为二叉排序树.二叉搜索树.对于树中每一个节点X,它的左子树中所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项.二叉查找树的平均深度为O(log ...

  3. C# 校验并转换 16 进制字符串到字节数组

    问题 最近在进行硬件上位机开发的时候,经常会遇到将 16 进制字符串转换为 byte[] 的情况,除了这种需求以外,还需要判定一个字符串是否是有效的 16 进制数据. 解决 字符串转 byte[] 的 ...

  4. Web前端基础(5):CSS(二)

    1. 盒模型 在CSS中,"box model"这一术语是用来设计和布局时使用,然后在网页中基本上都会显示一些方方正正的盒子.我们称为这种盒子叫盒模型. 盒模型有两种:标准模型和I ...

  5. Linux网络——配置网络之ifconfig家族命令

    Linux网络——配置网络之ifconfig家族命令 摘要:本文主要学习了ifconfig家族用来配置网络的命令. ifconfig命令 ifconfig命令用来显示或设置网络接口信息,设置只是临时生 ...

  6. 使用Fiddler进行HTTP流量分析

    - 安装 Fiddler是一款免费软件,可以到其官网下载,地址是https://www.telerik.com/fiddler,也可以从我的网盘中下载,发送"fiddler"获取下 ...

  7. DIY客户端框架

    C/S类型的客户端做过好多轮了,在架构上每次都调整优化一部分,慢慢的形成了DIY的框架性东西. 可是最近这一看呢,已经不像MVC了,然后有一天看到了MVP概念,咦!很像.再一看,嗯,就该是MVP. M ...

  8. Pi Network有梦想是好的,最新消息和下载注册流程。

    (注册流程最下面) ---------------------------------------------------------------------------------- 今日更新(10 ...

  9. Python类的定义、方法和属性使用

    类用来描述具有相同的属性和方法的对象的集合.对于在类中定义的函数,称为方法.类变量不直接叫做类变量,称为属性. 1.类的定义 例子: class User(): pass 说明: (1)定义了一个类名 ...

  10. crawlscrapy简单使用方法

    crawlscrapy简单使用方法 1.创建项目:scrapy startproject 项目名例如:scrapy startproject wxapp windows下,cmd进入项目路径例如d:\ ...