O(nlogn longn)的算法,数据5e5
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e6+10;
unsigned int tree[N][26],idx;
unsigned int cnt[N];
unsigned long long pw1[N],h1[N];
char s[N];
inline void insert(){
unsigned int n=strlen(s+1);
unsigned int cur=0;
cnt[cur]=1;
for(unsigned int i=1;i<=n;i++){
unsigned int v=s[i]-'a';
if(!tree[cur][v]) tree[cur][v]=++idx;
cur=tree[cur][v];
cnt[cur]=1;
}
}
inline void dfs(unsigned int u){
for(unsigned int i=0;i<26;i++){
if(tree[u][i]){
dfs(tree[u][i]);
cnt[u]+=cnt[tree[u][i]];
}
}
}
unsigned long long mp[N];unsigned int tot;
unsigned int mp2[N];
pair<unsigned long long,unsigned int>ddd[N];
void dfs2(unsigned int u,unsigned long long h1){
ddd[tot++]={h1,cnt[u]};
for(unsigned int i=0;i<26;i++){
if(tree[u][i]){
dfs2(tree[u][i],h1*31+i+1);
}
}
}
unsigned int n,m;
inline unsigned int find2(unsigned int l,unsigned int r,unsigned long long v){
while(l<=r){
int mid=(l+r)>>1;
if(mp[mid]>v) r=mid-1;
else{
if(mp[mid]==v) return mid;
else l=mid+1;
}
}
return 2147483647;
}
int main(){
scanf("%d%d",&n,&m);
for(unsigned int i=1;i<=n;i++){
scanf("%s",s+1);
insert();
}
dfs(0);
dfs2(0,0);
stable_sort(ddd,ddd+tot);
for(unsigned int i=0;i<tot;i++){
mp[i]=ddd[i].first;
mp2[i]=ddd[i].second;
}
scanf("%s",s+1);
pw1[0]=1;
for(unsigned int i=1;i<=m;i++) pw1[i]=pw1[i-1]*31;
for(unsigned int i=1;i<=m;i++) h1[i]=h1[i-1]*31+s[i]-'a'+1;
for(unsigned int i=1;i<=m;i++){
if(find2(0,tot-1,s[i]-'a'+1)==2147483647){
printf("0 %d\n",cnt[0]);
continue;
}
unsigned int l=i,r=m;unsigned int mid;
while(l<r){
mid=(l+r+1)>>1;
unsigned long long u=h1[mid]-h1[i-1]*pw1[mid-i+1];
unsigned long long c=2147483647;
unsigned int l1=0,r1=tot-1;int mid1;
while(l1<=r1){
mid1=(l1+r1)>>1;
if(mp[mid1]>u) r1=mid1-1;
else{
if(mp[mid1]==u){
c=mid1;
break;
}
else l1=mid1+1;
}
}
if((c^2147483647)&&mp[c]==u) l=mid;
else r=mid-1;
}
unsigned long long u=h1[l]-h1[i-1]*pw1[l-i+1];
unsigned int c=find2(0,tot-1,u);
printf("%d %d\n",l-i+1,mp2[c]);
}
return 0;
}