小 ω \omega ω 有很多字符串,它们都由小写字母构成。
给你 n n n 个字符串 a i a_i ai ,和 Q Q Q 个询问,每次对两个串 S = a i , T = a j S = a_i, T = a_j S=ai,T=aj 询问最大的 L ( 0 ≤ L ≤ min { ∣ S ∣ , ∣ T ∣ } ) L(0 \leq L \leq \min\{|S|,|T|\}) L(0≤L≤min{ ∣S∣,∣T∣}) 使得 S [ ∣ S ∣ − L + 1 … ∣ S ∣ ] = T [ 1 … L ] S[|S| - L + 1 \dots |S|] = T[1\dots L] S[∣S∣−L+1…∣S∣]=T[1…L] 。
第一行两个正整数 n , Q , n, Q, n,Q, 表示一共有 n n n 个字符串,以及有 Q Q Q 个询问。
下面 n n n 行,每行一个字符串 a i a_i ai。
下面 Q Q Q 行,每行两个正整数 x , y , x, y, x,y, 表示询问 S = a x S = a_x S=ax 和 T = a y T = a_y T=ay。
输出 Q Q Q 行,每行一个非负整数,表示最大的 L L L。
样例输入
3 6
wwq
eew
qwe
1 2
2 3
1 3
2 1
3 2
3 1
样例输出
0
0
1
1
1
0
对于所有数据,保证 ∣ a i ∣ ≥ 1 , ∑ i = 1 n ∣ a i ∣ ≤ 6 × 1 0 5 , 1 ≤ 1 0 6 |a_i| \geq 1, \sum_{i = 1} ^ {n} |a_i| \leq 6 \times 10^5, 1 \leq 10^6 ∣ai∣≥1,∑i=1n∣ai∣≤6×105,1≤106。
对于第 1 ∼ 2 1 \sim 2 1∼2 组数据,保证 n = 1 n = 1 n=1。
对于第 3 ∼ 6 3 \sim 6 3∼6 组数据,保证 n ≤ 10 n \leq 10 n≤10。
对于第 7 ∼ 10 7 \sim 10 7∼10 组数据,保证 ∑ i = 1 n ∣ a i ∣ ≤ 5 × 1 0 3 \sum_{i = 1} ^ { n} |a_i| \leq 5 \times 10^3 ∑i=1n∣ai∣≤5×103。
对于第 11 ∼ 14 11 \sim 14 11∼14 组数据,保证只出现 a b ab ab 两种字符,且 ∑ i = 1 n ∣ a i ∣ ≤ 5 × 1 0 4 \sum_{i = 1} ^ { n} |a_i| \leq 5 \times 10^4 ∑i=1n∣ai∣≤5×104。
对于第 15 ∼ 20 15 \sim 20 15∼20 组数据,没有特殊限制。
镇海中学 csp2020 模拟2
题解:
暴力过了。。
考虑暴力 H a s h Hash Hash 匹配,同时记忆化, O ( n n ) O(n\sqrt n) O(nn)。
#include<bits/stdc++.h>
#define N 1000005
typedef unsigned long long ll;
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){
x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const ll P1=133331,P2=998244353;
const int T=6000;
ll p1[N],p2[N];
vector<ll> a1[N],a2[N];
int len[N];
char s[N];
int to[N],q[N],pre[T+5][T+5],b[T+5][T+5];
struct node{
int len,id;
}pai[N];
int pt;
bool cmp(node a,node b){
return a.len>b.len;}
int main(){
//freopen("string.in","r",stdin);
// freopen("string.out","w",stdout);
//printf("%d\n",sizeof(pre)>>20);
int n=read(),Q=read();
p1[0]=p2[0]=1;
for(int i=1;i<N;++i)p1[i]=p1[i-1]*P1,p2[i]=p2[i-1]*P2;
//int ke=1;
int las=0;
for(int i=1;i<=n;++i){
scanf("%s",1+s);
a1[i].push_back(0);
a2[i].push_back(0);
len[i]=strlen(1+s);
pai[++pt].len=len[i],pai[pt].id=i;
for(int j=1;j<=len[i];++j){
ll now=s[j]-'a';
a1[i].push_back(a1[i][j-1]*P1+now);
a2[i].push_back(a2[i][j-1]*P2+now);
//ll now=(a[i][j-1]*P+s[j]-'a');
//cout<<s[j]<<endl;
//h1[i][a1[i][j]]=1;
//h2[i][a2[i][j]]=1;
}
}
sort(pai+1,pai+1+n,cmp);
for(int i=1;i<=min(T,n);++i){
q[++q[0]]=pai[i].id;
to[pai[i].id]=q[0];
}
while(Q--){
int x=read(),y=read();
if(to[x]&&to[y]&&b[to[x]][to[y]]){
printf("%d\n",pre[to[x]][to[y]]);
continue;
}
int r=min(len[x],len[y]),ans=0;
for(int i=r;i;--i){
ll now1=a1[x][len[x]]-a1[x][len[x]-i]*p1[i],now2=a2[x][len[x]]-a2[x][len[x]-i]*p2[i];
ll to1=a1[y][i],to2=a2[y][i];
if(now1==to1&&now2==to2){
ans=i;break;
}
}
//cout<<len[x]<<" "<<len[y]<<endl;
//cout<<x<<" "<<y<<endl;
//cout<<a1[y][2]<<" "<<a1[x][len[x]]-a1[x][len[x]-2]*P1*P1<<endl;
if(to[x]&&to[y]){
b[to[x]][to[y]]=1;
pre[to[x]][to[y]]=ans;
}
printf("%d\n",ans);
}
return 0;
}
/*
2 1
ababab
bbbbbb
1 2
*/