【长郡NOIP2014模拟10.22】字符串查询

2024-05-29 03:08

本文主要是介绍【长郡NOIP2014模拟10.22】字符串查询,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

给定n个字符串和q个询问
每次询问在这n个字符串中,有多少个字符串同时满足
1. 字符串a是它的前缀
2. 字符串b是它的后缀

Input

第一行两个数n,q ,表示给定字符串数和询问数
接下来n行每行一个字符串
再接下来q组询问,每组询问2行,分别表示两个字符串a,b,意义上述

Output

q行每行一个数,表示有多少个字符串满足条件

Sample Input

4 2
abc
bac
ac
acc
a
c
ba
ac

Sample Output

3
1
【友情提示】
字符串全部由小写字母a到j组成,行末保证没有多余字符,没有多余的空行,没有空串

Data Constraint

30%数据满足n,q≤1000
另有30%数据满足n,q≤50000,所有询问中a,b串长度丌超过2
100%数据满足n,q≤50000,字符串长度丌超过100,任意两串最长公共前缀较短

Solution

时限很大,意思就是让你排序的
怕被卡的话就把它压成十进制数然后排序(字母只有a~j共10个)
按照前缀和后缀分别排序,那么每个字符串都有前缀的名次x和后缀的名次y
把每个字符串想象成一个点(x,y)
那么询问时的前缀就一定是一个连续的区间[l,r]
同理,后缀也是连续的区间[a,b]
这里的a,b,l,r都可以用二分求出,也可以都加入到原序列中一起排序得出
那么变成求在这两个区间的交集中有多少个点

离线处理
对于询问,拆成两个即x为1~l区间和1~r区间,用后者-前者
从小到大排序,然后对于某个询问的z可能属于原来询问的后者或前者,判断一下就好
用树状数组维护此时(x=1-z)时y的个数,询问时调用就行了
c++排序建议用sort,二分因为我不会用upperbound之类的所以打了四个,判断大小也打了四个……

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 101000
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int n,q,ans[N],e[N*2],bz[N];
struct note{char a[110];int n,z;
}s[N],t[N];struct node{int x,y,z,r;
}c[N],b[N];bool cnt(node x,node y){return x.x<y.x;}
bool cmt(note x,note y)
{fo(i,1,min(x.n,y.n)){if(x.a[i]<y.a[i]) return 1;if(x.a[i]>y.a[i]) return 0;}if(x.n<y.n) return 1;else return 0;
}
bool cmt2(note x,note y)
{fo(i,1,min(x.n,y.n)){if(x.a[x.n-i+1]<y.a[y.n-i+1]) return 1;if(x.a[x.n-i+1]>y.a[y.n-i+1]) return 0;}if(x.n<y.n) return 1;else return 0;
}
bool same(note x,note y)
{fo(i,1,y.n)if(x.a[i]!=y.a[i]) return 0;return 1;
}
bool same1(note x,note y)
{fo(i,1,y.n)if(x.a[x.n-i+1]!=y.a[y.n-i+1]) return 0;return 1;
}
bool cnt1(note x,note y)
{fo(i,1,x.n) {if(x.a[i]<y.a[i]) return 1;if(x.a[i]>y.a[i]) return 0;}return 1;
}
bool cnt2(note x,note y)
{fo(i,1,x.n) {if(x.a[i]>y.a[i]) return 1;if(x.a[i]<y.a[i]) return 0;}return 1;
}
bool cnt3(note x,note y)
{fo(i,1,x.n) {if(x.a[x.n-i+1]<y.a[y.n-i+1]) return 1;if(x.a[x.n-i+1]>y.a[y.n-i+1]) return 0;}return 1;
}
bool cnt4(note x,note y)
{fo(i,1,x.n) {if(x.a[x.n-i+1]>y.a[y.n-i+1]) return 1;if(x.a[x.n-i+1]<y.a[y.n-i+1]) return 0;}return 1;
}
int ef1(int l,int r,note z)
{while(l+1<r){int m=(l+r)/2;if(cnt1(z,s[m])) r=m;else l=m;}if(same(s[l],z)) r=l;return r;
}
int ef2(int l,int r,note z)
{while(l+1<r){int m=(l+r)/2;if(cnt3(z,t[m])) r=m;else l=m;}if(same1(t[l],z)) r=l;return r;
}
int ef3(int l,int r,note z)
{while(l+1<r){int m=(l+r)/2;if(cnt4(z,t[m])) l=m;else r=m;}if(same1(t[r],z)) l=r;return l;
}
int ef4(int l,int r,note z)
{while(l+1<r){int m=(l+r)/2;if(cnt2(z,s[m])) l=m;else r=m;}if(same(s[r],z)) l=r;return l;
}
int lowbit(int x){return x&(-x);}
void insert(int x)
{for(;x<=n;x+=lowbit(x)) e[x]++;
}
int get(int x)
{int an=0;for(;x;x-=lowbit(x)) an+=e[x];return an;
}
int main()
{scanf("%d%d\n",&n,&q);fo(i,1,n) scanf("%s\n",s[i].a+1),s[i].n=strlen(s[i].a+1),s[i].z=i,t[i]=s[i];sort(s+1,s+n+1,cmt);fo(i,1,n) c[s[i].z].x=i;sort(t+1,t+n+1,cmt2);fo(i,1,n) c[t[i].z].y=i;int tot=0;fo(i,1,q){note x,y;scanf("%s\n",x.a+1);scanf("%s\n",y.a+1);x.n=strlen(x.a+1),y.n=strlen(y.a+1);int jy1=ef2(1,n,y);int jy2=ef3(1,n,y);b[++tot].x=ef1(1,n,x);b[tot].y=jy1;b[tot].r=jy2;b[tot].z=i;b[++tot].x=ef4(1,n,x)+1;b[tot].y=jy1;b[tot].r=jy2;b[tot].z=i;}sort(c+1,c+n+1,cnt);sort(b+1,b+tot+1,cnt);int j=1;fo(i,1,tot){for(;c[j].x<b[i].x&&j<=n;j++) insert(c[j].y);int jy=get(b[i].r);jy -=get(b[i].y-1);if(bz[b[i].z]==0) ans[b[i].z]-=jy,bz[b[i].z]=1;else ans[b[i].z]+=jy;}fo(i,1,q) printf("%d\n",ans[i]);
}

这篇关于【长郡NOIP2014模拟10.22】字符串查询的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1012471

相关文章

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

查询SQL Server数据库服务器IP地址的多种有效方法

《查询SQLServer数据库服务器IP地址的多种有效方法》作为数据库管理员或开发人员,了解如何查询SQLServer数据库服务器的IP地址是一项重要技能,本文将介绍几种简单而有效的方法,帮助你轻松... 目录使用T-SQL查询方法1:使用系统函数方法2:使用系统视图使用SQL Server Configu

C#从XmlDocument提取完整字符串的方法

《C#从XmlDocument提取完整字符串的方法》文章介绍了两种生成格式化XML字符串的方法,方法一使用`XmlDocument`的`OuterXml`属性,但输出的XML字符串不带格式,可读性差,... 方法1:通过XMLDocument的OuterXml属性,见XmlDocument类该方法获得的xm

MYSQL关联关系查询方式

《MYSQL关联关系查询方式》文章详细介绍了MySQL中如何使用内连接和左外连接进行表的关联查询,并展示了如何选择列和使用别名,文章还提供了一些关于查询优化的建议,并鼓励读者参考和支持脚本之家... 目录mysql关联关系查询关联关系查询这个查询做了以下几件事MySQL自关联查询总结MYSQL关联关系查询

Java实现Elasticsearch查询当前索引全部数据的完整代码

《Java实现Elasticsearch查询当前索引全部数据的完整代码》:本文主要介绍如何在Java中实现查询Elasticsearch索引中指定条件下的全部数据,通过设置滚动查询参数(scrol... 目录需求背景通常情况Java 实现查询 Elasticsearch 全部数据写在最后需求背景通常情况下

查询Oracle数据库表是否被锁的实现方式

《查询Oracle数据库表是否被锁的实现方式》本文介绍了查询Oracle数据库表是否被锁的方法,包括查询锁表的会话、人员信息,根据object_id查询表名,以及根据会话ID查询和停止本地进程,同时,... 目录查询oracle数据库表是否被锁1、查询锁表的会话、人员等信息2、根据 object_id查询被

JSON字符串转成java的Map对象详细步骤

《JSON字符串转成java的Map对象详细步骤》:本文主要介绍如何将JSON字符串转换为Java对象的步骤,包括定义Element类、使用Jackson库解析JSON和添加依赖,文中通过代码介绍... 目录步骤 1: 定义 Element 类步骤 2: 使用 Jackson 库解析 jsON步骤 3: 添

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

数据库oracle用户密码过期查询及解决方案

《数据库oracle用户密码过期查询及解决方案》:本文主要介绍如何处理ORACLE数据库用户密码过期和修改密码期限的问题,包括创建用户、赋予权限、修改密码、解锁用户和设置密码期限,文中通过代码介绍... 目录前言一、创建用户、赋予权限、修改密码、解锁用户和设置期限二、查询用户密码期限和过期后的修改1.查询用

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu