1. 程式人生 > >[CTSC2014] 企鵝QQ

[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 }