正解未理解,先用哈希写。
题目描述
阿轩在纸上写了两个字符串,分别记为A和B。
利用在数据结构与算法课上学到的知识,他很容易地求出了“字符串A从任意位置开始的后缀子串”与“字符串B”匹配的长度。
不过阿轩是一个勤学好问的同学,他向你提出了Q个问题:
在每个问题中,他给定你一个整数x,请你告诉他有多少个位置,满足“字符串A从该位置开始的后缀子串”与B匹配的长度恰好为x。
例如:A=aabcde,B=ab,则A有aabcde、abcde、bcde、cde、de、e这6个后缀子串,它们与B=ab的匹配长度分别是1、2、0、0、0、0。
因此A有4个位置与B的匹配长度恰好为0,有1个位置的匹配长度恰好为1,有1个位置的匹配长度恰好为2。
输入格式
第一行输入三个整数N,M,Q,分别表示A串长度、B串长度、问题个数。
第二行输入字符串A,第三行输入字符串B。
接下来Q行每行输入1个整数x,表示一个问题。
输出格式
输出共Q行,依次表示每个问题的答案。
数据范围
1≤N,M,Q,x≤200000
样例
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int N=200000+10,P=131;
ULL h1[N],h2[N],p[N];
// h1[] 储存s1的哈希数组;
// h2[] 储存s2的哈希数组;
// p[] 储存p的i倍 (用来平衡倍数差,使之可以相减);
int n,m,q,K[N];
// K[] 储存该长度的点数;
char s1[N],s2[N];
ULL f1(int q,int h){ // 求s1[q]到s1[h]的哈希表示;
return h1[h]-h1[q-1]*p[h-q+1];
}
ULL f2(int q,int h){ // 求s2[q]到s2[h]的哈希表示;
return h2[h]-h2[q-1]*p[h-q+1];
}
int main(){
scanf("%d%d%d%s%s",&n,&m,&q,s1+1,s2+1);// 输入;
p[0]=1;
for(int i=1;i<=n;i++) p[i]=p[i-1]*P;
for(int i=1;i<=n;i++) h1[i]=h1[i-1]*P+s1[i];
for(int i=1;i<=m;i++) h2[i]=h2[i-1]*P+s2[i];// 哈希处理;
for(int i=1;i<=n;i++){
if(s1[i]!=s2[1]){
K[0]++;
continue;
}
int l=1,r=min(m,n+1-i);
while(l!=r){
int zj=(l+r+1)/2;
if(f2(1,zj)==f1(i,i+zj-1)) l=zj;
else r=zj-1;
}
++K[l];
}
while(q--){
int k;
scanf("%d",&k);
printf("%d\n",K[k]);
}
return 0;
}
先将俩字符串用哈希储存。
再将以s1各个点为起点的匹配长度打表。
最后逐个输入长度并输出该长度的点数。
ps : 范围过大,需用二分。
如有不足,请多指教。