UVALive 6047 Perfect Matching(字符串哈希)#by zh

周三做这场比赛的练习,这题过的人挺多的,但是一直没有好的思路。当时想的时候以为是字典树,但是具体的不知道该怎么做,后来看别人AC的代码才知道用简单的字符串哈希,或者其他的比如字母个数的限制条件优化一下就能过了,确实挺简单的,当时没有想到。写这题也没找什么字符串哈希的函数就是简单的哈希一下,如果相同再枚举判断一下就好了,有人可能对自己的哈希函数(或者说是人品)太自信,哈希值一样就认为是回文,我那样的策略不再判断是会WA的,判断后也不太慢632ms
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
char str[1005][505];
char antistr[1005][505];
long long hash[2][1005];
int len[1005];
long long po[505];
long long change(char* str,int len)
{
    long long temp=0;
    for(int i=0;i<len;i++)
    {
        temp=26*temp+str[i]-'a';
    }
    return temp;
}
bool judge(int x,int y)
{
    long long s1=hash[0][x]*po[len[y]]+hash[0][y],s2=hash[1][y]*po[len[x]]+hash[1][x];
    if(s1!=s2)
        return false;
    else
    {
        string temp="";
        temp+=str[x];
        temp+=str[y];
        int len=temp.size();
        for(int i=0;i<len/2;i++)
        {
            if(temp[i]!=temp[len-i-1])
                return false;
        }
    }
    return true;
}
int main()
{
    //freopen("input.txt","r",stdin);
    po[0]=1;
    for(int i=1;i<=500;i++)
        po[i]=po[i-1]*26;
    int t;
    scanf("%d",&t);
    for(int cas=1;cas<=t;cas++)
    {
        printf("Case #%d: ",cas);
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%s",str[i]);
            len[i]=strlen(str[i]);
            hash[0][i]=change(str[i],len[i]);
            for(int j=0;j<len[i];j++)
                antistr[i][j]=str[i][len[i]-j-1];
            hash[1][i]=change(antistr[i],len[i]);
        }
        int ans=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                if(i==j)
                    continue;
                if(judge(i,j))
                    ans++;
            }
        printf("%d\n",ans);
    }
}

你可能感兴趣的:(UVALive 6047 Perfect Matching(字符串哈希)#by zh)