字符串匹配

【题目描述】

对于一个字符集大小为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. JNDI和JDBC的区别-个人理解

    网上关于JNDI和JDBC的定义有很多,但是都很官方不容易理解,下面是我最近查阅资料得出的心得体会.希望对你在理解上有一点点的帮助,说的不对的请指正哦. JDBC: 看到最多的就是 Java Data ...

  2. ES6入门 阮一峰

    ECMAScript 6 入门 http://es6.ruanyifeng.com/#README 在线ES6转ES5 https://es6console.com/k11vgg1r/

  3. Java泛型类型擦除与运行时类型获取

    Java的泛型大家都知道是类型擦除的方式实现的,“编译器会进行泛型擦除”是一个常识了(实际擦除的是参数和自变量的类型).“类型擦除” 并非像许多开发者认为的那样,在 <..> 符号内的东西 ...

  4. serf 中去中心化系统的原理和实现

    原文:https://www.infoq.cn/article/principle-and-impleme-of-de-centering-system-in-serf serf 是出自 Hashic ...

  5. Python3---爬虫---抓取百度贴吧

    前言 该文章主要描述如何抓取百度贴吧内容.当然是简单爬虫实现功能,没有实现输入参数过滤等辅助功能,仅供小白学习. 修改时间:20191219 天象独行 import os,urllib.request ...

  6. 怎样深入学习php,成为php高手!?

    本文章开头我想问一句话:PHP是做什么的? 因为这是面试中会问到的一个问题,虽然它看起来很简单,回答做网站的,也就是个简单建站的水平.回答做网站后端开发的,对PHP有了一定的认识,回答做后端处理的,有 ...

  7. Vue常用语法

    一.模板语法 1.双大括号表达式 [语法:] {{exp}} 用于向页面输入数据,即页面显示数据. [举例:] <!doctype html> <html lang="en ...

  8. vue学习笔记(一): 建立 vue-cli 初始网站

    在安装vue-cli之前,要先安装node.js这个大家百度一下就可以了 1.安装 vue-cli npm install -g @vue/cli-init 2.初始化一个项目,名为 hcmanage ...

  9. 证书锁定SSL/TLS Pinning

    前言 APP端抓包中, 设置抓包代理后会发现部分APP(如app store.Facebook)直接无法访问,其他部分app又功能正常,为什么呢?这涉及 ssl-pinning,证书锁定. 证书锁定( ...

  10. js验证手机号、身份证等

    //验证手机号function check_lxdh(lxdh){ var mobile = /^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0 ...