题解:
通过观察可以发现,其实题目就是要求长度相等的字符串中有且只有1位字符不同的 ”字符串对“ 有多少。
因为数据范围不大, 所以考虑一种暴力至极的方法。
我们枚举是哪一位不同,然后通过hash验证,同时为了加速,我们先求出每一个字符串的前缀hash数组和后缀hash数组,
如果是枚举到第j位不同,我们就合并前缀hash[j-1]和后缀hash[j+1],然后判断是否相等即可。
因为是求点对,因此还要考虑组合数,所以我们判断的时候顺便求出组合数即可
1 // luogu-judger-enable-o2 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define R register int 5 #define LL unsigned long long 6 #define AC 30010 7 #define ac 250 8 int n, m, k, ans; 9 LL H[AC][ac], G[AC][ac], tmp[AC]; 10 char s[AC]; 11 12 void cal(int x)//处理出2个整串的hash数组,然后再去除枚举的j并合并 13 { 14 for(R i = 1; i <= m; i++) H[x][i] = H[x][i - 1] * 149 + s[i]; 15 for(R i = m; i; i--) G[x][i] = G[x][i + 1] * 137 + s[i]; 16 } 17 18 void pre() 19 { 20 scanf("%d%d%d", &n, &m, &k); 21 for(R i = 1; i <= n; i++) 22 { 23 scanf("%s", s + 1); 24 cal(i); 25 } 26 } 27 28 void work() 29 { 30 int t; 31 for(R j = 1; j <= m; j++)//枚举删掉哪位 32 { 33 for(R i = 1; i <= n; i++)//获取每个串的hash值 34 tmp[i] = H[i][j-1] * 233 + G[i][j + 1] * 213; 35 sort(tmp + 1, tmp + n + 1); 36 t = 1; 37 for(R i = 2; i <= n; i++)//看有多少相同串,顺便统计组合数 38 if(tmp[i] == tmp[i - 1]) ans += t, ++t; 39 else t = 1;//不然就重置,如果有2个相同,显然不能只计一个,所以初始值为1 40 41 } 42 printf("%d\n", ans); 43 } 44 45 int main() 46 { 47 // freopen("in.in", "r", stdin); 48 pre(); 49 work(); 50 // fclose(stdin); 51 return 0; 52 }