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

 

posted @ 2017-11-25 21:17  AKCqhzdy  阅读(199)  评论(0编辑  收藏  举报