正解是trie树。。。在树上跳来跳去什么的
然而在企鹅qq那题的影响下我写了hash。。。
添加一个字母到一个串,就相当于另一个串删对应位置上的字母。
改变某个位置上的字母,就相当于两个字符串删掉同一个位置上的字母。
所以要记录的东西也不多。。存一下每个串删掉每个位置上的字母后的hash值并排序,然后查询的时候二分一下就行了。
但要注意的是,两个字符串可能有多种编辑方式。。。比方说字符串cccc,分别删掉四个位置上的字母后得到的都是ccc。。
所以一开始要再去一下重。(要不是老司机提醒我还不知道要调多久TAT
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ull unsigned long long 6 using namespace std; 7 const int maxn=10023; 8 ull mp[21][maxn]; 9 ull b[21],jc[21],pre[21]; 10 ull map[20*maxn]; 11 int len[maxn],num[21]; 12 int i,j,k,n,m,l,r,mid,cnt,ans; 13 char s[23]; 14 inline int getl(int x,ull v){ 15 for(l=1,r=num[x];l<r;) 16 if(mp[x][mid=(l+r)>>1]<v)l=mid+1;else r=mid; 17 return mp[x][l]==v?l:0; 18 } 19 inline int getr(int x,ull v){ 20 for(l=1,r=num[x];l<r;) 21 if(mp[x][mid=(l+r+1)>>1]<=v)l=mid;else r=mid-1; 22 return mp[x][l]==v?l:0; 23 } 24 inline int get(int ull v){ 25 int posl; 26 for(l=1,r=cnt;l<r;) 27 if(map[mid=(l+r)>>1]<v)l=mid+1;else r=mid; 28 if(map[l]!=v)return 0; 29 if(map[l+1]!=v)return 1; 30 posl=l; 31 for(l=posl,r=cnt;l<r;) 32 if(map[mid=(l+r+1)>>1]<=v)l=mid;else r=mid-1; 33 return l-posl+1; 34 } 35 int main(){ 36 register int j; 37 scanf("%d%d",&n,&m); 38 for(i=jc[0]=1;i<=20;i++)jc[i]=jc[i-1]*233; 39 int mx=0;num[0]=n; 40 for(i=1;i<=n;i++){ 41 scanf("%s",s);len[i]=strlen(s); 42 for(j=1;j<=len[i];j++)pre[j]=pre[j-1]*233+s[j-1]; 43 for(j=1;j<=len[i];j++) 44 mp[j][++num[j]]=pre[len[i]]-pre[j]*jc[len[i]-j]+pre[j-1]*jc[len[i]-j]; 45 mp[0][i]=pre[len[i]]; 46 mx=max(mx,len[i]); 47 for(j=1;j<=len[i];j++)b[j]=mp[j][num[j]]; 48 sort(b+1,b+1+len[i]); 49 for(j=len[i];j;j--)if(j==len[i]||b[j+1]!=b[j])map[++cnt]=b[j];//,printf(" %lld ",b[j]); 50 // printf("! %lld ",mp[1][num[1]]); 51 } 52 for(i=0;i<=mx;i++)sort(mp[i]+1,mp[i]+1+num[i]); 53 sort(map+1,map+1+cnt); 54 // for(i=0;i<=mx;i++){ 55 // for(j=1;j<=num[i];j++)printf(" %lld",mp[i][j]);puts(""); 56 // } 57 ull tmp; 58 while(m--){ 59 scanf("%s",s);int len=strlen(s); 60 for(j=1;j<=len;j++)pre[j]=pre[j-1]*233+s[j-1]; 61 if((k=getl(0,pre[len]))){puts("-1");continue;} 62 63 ans=get(pre[len]);//printf(" %d ",ans); 64 for(j=1;j<=len;j++){ 65 tmp=b[j]=pre[len]-pre[j]*jc[len-j]+pre[j-1]*jc[len-j]; 66 if((k=getl(j,tmp)))ans+=getr(j,tmp)-k+1; 67 } 68 69 sort(b+1,b+1+len); 70 for(j=len;j;j--) 71 if(j==len||b[j+1]!=b[j]) 72 if((k=getl(0,b[j]))) 73 ans+=getr(0,b[j])-k+1; 74 75 printf("%d ",ans); 76 } 77 return 0; 78 }