[CTSC2014] 企鹅QQ

洛谷 P4503 传送门

这种东西一看就是字符串hash搞。

先从前往后哈希一遍,再从后往前哈希一遍。

这样我们就可以O(1)提取出去掉某一位的哈希值。

接下来考虑计算相似字符串的数目。

总数=仅在第一位不一样的+仅在第二位不一样的+......+仅在第L位不一样的。

我们先枚举每一位,再把每个字符串去掉这一位的哈希值算出来,看有没有重复的。

判重方法有很多,我用的是排序之后再计算的方法。

有个诡异的地方,算去掉某一位的哈希值tmp的时候,如果两边的哈希值相加之前不分别乘seed,会狂wa不止......

我也不知道为什么。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 typedef unsigned long long ull;
 6 
 7 const int sd[2]={107,127};
 8 int n,l,s;
 9 ull mul[205];
10 ull hs[30005][205][2];
11 int ans;
12 
13 int main()
14 {
15     scanf("%d%d%d",&n,&l,&s);
16     for(int i=1;i<=n;i++)
17     {
18         char str[205];
19         scanf("%s",str+1);
20         for(int j=1;j<=l;j++)
21             hs[i][j][0]=hs[i][j-1][0]*sd[0]+str[j]-'@'+1;
22         for(int j=l;j;j--)
23             hs[i][j][1]=hs[i][j+1][1]*sd[1]+str[j]-'@'+1;
24     }
25     ull tmp[30005];
26     for(int i=1;i<=l;i++)
27     {
28         for(int j=1;j<=n;j++)
29             tmp[j]=hs[j][i-1][0]*sd[0]+hs[j][i+1][1]*sd[1];
30         sort(tmp+1,tmp+n+1);
31         int nw=1;
32         for(int j=2;j<=n;j++)
33         {
34             if(tmp[j]==tmp[j-1])ans+=nw,nw++;
35             else nw=1;
36         }
37     }
38     printf("%d",ans);
39     return 0;
40 }

 

posted @ 2018-11-06 20:32  cervusky  阅读(233)  评论(0编辑  收藏  举报

Contact with me