bzoj3555: [Ctsc2014]企鹅QQ
最近几天感冒,挖了很多坑,趁今晚状态还可以,赶紧填一填,重新写了一次代码,思路大同小异,但是就是A了,可能是状态问题,细节没有做好吧。
这道题一开始就是想到hash了,但是错误的想只比较一次,然后果断WA
正确的做法应该是枚举每一个n-1长度的串,然后比较他们之间是否相同,由于题意说明没有相同的串,那么当某一长度为n-1的串相互相等,实际上他们就是相似了。然后传统的枚举两个串是否相等,即使用了hash令比较的时间复杂度为O(1),但是枚举量依然达到了O(n^2)。这时就有一个小技巧,通过排序hash值令其有序,当x-2!=x-1 时,毫无疑问的x并不可能和x-2相等,那么实际操作上可以说是O(n)的,那么时间复杂度就是枚举的L乘上排序的nlogn。
#include<cstdio> #include<algorithm> using namespace std; typedef long long LL; const int p=131; LL Bin[210]; LL a[31000],hash[31000]; char s[31000][210]; int main() { Bin[0]=1;for(int i=1;i<=200;i++)Bin[i]=Bin[i-1]*p; int n,L,haha; scanf("%d%d%d",&n,&L,&haha); for(int i=1;i<=n;i++)scanf("%s",s[i]+1); for(int i=1;i<=n;i++) for(int j=1;j<=L;j++) hash[i]=hash[i]*p+s[i][j]; int ans=0; for(int j=1;j<=L;j++) { for(int i=1;i<=n;i++)a[i]=hash[i]-s[i][j]*Bin[L-j]; sort(a+1,a+n+1); int sum=1; for(int i=2;i<=n;i++) if(a[i]==a[i-1])sum++; else ans+=sum*(sum-1)/2,sum=1; ans+=sum*(sum-1)/2; } printf("%d\n",ans); return 0; }
pain and happy in the cruel world.