题目大意
给出nnn个长度为lll且互不相同的串,若两个串只有一个字符不相同那么这两个串相似。
求有多少对相似的串。
解题思路
我们可以枚举不相似的位,然后我们考虑字符串hashhashhash
然后我们可以将删掉了一位的字符串拆分为由[1..k−1][1..k-1][1..k−1]和[k+1..l][k+1..l][k+1..l]组成的字符串。
我们先正着求一遍hashhashhash定为hashihash_ihashi,然后倒着求一遍hashhashhash定为dhashidhash_idhashi。
然后删除第kkk位之后的hashhashhash值为hashk+dhashk∗pkhash_k+dhash_k*p^khashk+dhashk∗pk
然后排序统计即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ull unsigned long long
using namespace std;
const int N=30100,L=210;
const ull p=13331;
ull hash[N],hash1[N][L],hash2[N][L],pow;
int n,l,ans;
char s[N][L];
void work(int k)
{for(int i=1;i<=n;i++)hash[i]=hash1[i][k-1]+hash2[i][k+1]*pow;sort(hash+1,hash+1+n);hash[n+1]=23333333;int num=0;for(int i=1;i<=n;i++){num++;if(hash[i]!=hash[i+1])ans+=num*(num-1)/2,num=0;}
}
int main()
{scanf("%d%d%d",&n,&l,&pow);for(int i=1;i<=n;i++){scanf("%s",s[i]+1);for(int j=1;j<=l;j++)hash1[i][j]=hash1[i][j-1]*p+s[i][j];for(int j=l;j>=1;j--)hash2[i][j]=hash2[i][j+1]*p+s[i][j];}pow=1;for(int i=1;i<=l;i++)pow*=p,work(i);printf("%d",ans);
}