【长郡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 多列 IN 查询之语法、性能与实战技巧(最新整理)

《MySQL多列IN查询之语法、性能与实战技巧(最新整理)》本文详解MySQL多列IN查询,对比传统OR写法,强调其简洁高效,适合批量匹配复合键,通过联合索引、分批次优化提升性能,兼容多种数据库... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

MySQL 获取字符串长度及注意事项

《MySQL获取字符串长度及注意事项》本文通过实例代码给大家介绍MySQL获取字符串长度及注意事项,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 获取字符串长度详解 核心长度函数对比⚠️ 六大关键注意事项1. 字符编码决定字节长度2

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

XML重复查询一条Sql语句的解决方法

《XML重复查询一条Sql语句的解决方法》文章分析了XML重复查询与日志失效问题,指出因DTO缺少@Data注解导致日志无法格式化、空指针风险及参数穿透,进而引发性能灾难,解决方案为在Controll... 目录一、核心问题:从SQL重复执行到日志失效二、根因剖析:DTO断裂引发的级联故障三、解决方案:修复

mysql查询使用_rowid虚拟列的示例

《mysql查询使用_rowid虚拟列的示例》MySQL中,_rowid是InnoDB虚拟列,用于无主键表的行ID查询,若存在主键或唯一列,则指向其,否则使用隐藏ID(不稳定),推荐使用ROW_NUM... 目录1. 基本查询(适用于没有主键的表)2. 检查表是否支持 _rowid3. 注意事项4. 最佳实

MySQL存储过程之循环遍历查询的结果集详解

《MySQL存储过程之循环遍历查询的结果集详解》:本文主要介绍MySQL存储过程之循环遍历查询的结果集,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言1. 表结构2. 存储过程3. 关于存储过程的SQL补充总结前言近来碰到这样一个问题:在生产上导入的数据发现