zoukankan      html  css  js  c++  java
  • UVA-257 哈希算法

    UVA-257

    题意:

    给你很多串,你需要找到这个串内有没有两个长度大于3的回文字符串,且要保证这两个回文字符串不相同,也不能完全覆盖,但可以重合一部分

    题解:

    首先判断回文的话可以通过马拉车算法(Manacher算法),如果在某个位置上回文长度大于3的话就要判断一下,如果串长为奇数,那么就取3,否则取4。

    为什么呢?为了防止会完全覆盖

    如果在i位置上面串长为奇数,那么我们只会取3,例如bab。此时你应该在下一个位置(即,i+1)去判断,而不能还在i位置找回文串(因为这个会和之前的有覆盖关系)

    如果i+1位置回文串长度为奇数,例如babab(前面的bab是第i个位置的回文串),因为是奇数,我们只取3,所以只会取中间的3个,那么就不会和之前的有覆盖关系(其他情况你也可以自己去分析一下)

    到这里还没有完,我们避免了完全覆盖,但是还要注意两个不同位置的回文串可能会相同,所以可以用哈希+map来判重

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<sstream>
    #include<map>
    using namespace std;
    typedef unsigned long long ull;
    const int maxn=110010;
    char s[maxn],str[maxn*2];
    map<ull,int> mp;
    int Len[maxn*2],num;
    ull hash_[maxn],xp[maxn];
    void init_()
    {
        xp[0]=1;
        for(int i=1;i<maxn;i++)
            xp[i]=xp[i-1]*13331;
        return ;
    }
    void init(int len)  //这个是用来处理字符串的
    {
        memset(str,0,sizeof(str));
        int k=0;
        str[k++]='$';
        for(int i=0;i<len;++i)
            str[k++]='#',str[k++]=s[i];
        str[k++]='#';
        num=k;
    }
    void manacher(int len) //求最长回文子串
    {
        Len[0]=0;
        int sum=0;
        int id,mx=0;
        for(int i=1;i<len;++i)
        {
            if(i<mx)  Len[i]=min(mx-i,Len[2*id-i]);
            else Len[i]=1;
            while(str[i-Len[i]]==str[i+Len[i]]) Len[i]++;
            if(Len[i]+i>mx)
            {
                mx=Len[i]+i;
                id=i;
                sum=max(sum,Len[i]);
            }
        }
        //return (sum-1);
    }
    void make_hash(char str[])
    {
        int len=strlen(str);
        hash_[len]=0;
        for(int i=len-1;i>=0;i--)
        {
            hash_[i]=hash_[i+1]*13331+str[i]-'A'+1;
        }
        return ;
    }
    ull Get_hash(int i,int L)
    {
        return hash_[i]-hash_[i+L]*xp[L];
    }
    int main()
    {
        int ans=0;
        init_();
        while(scanf("%s",s)!=EOF)
        {
    
            mp.clear();
            int len=strlen(s);
            init(len);
            make_hash(s);
            manacher(num);//manacher之后,Mp[i]-1为i位置的回文半径
            int cnt=0;
            for(int i=0;i<2*len+2;i++)
            {
                if(Len[i]-1>=3)
                {
                    if(Len[i]%2==1)//回文串为偶数,取长度四的回文串
                    {
                        int st=(i-1)/2-2;
                        int le=4;
                        ull tmp=Get_hash(st,le);
                        mp[tmp]++;
                    }
                    else//回文串为奇数,取长度三的回文串
                    {
                        int st=i/2-2;
                        int le=3;
                        ull tmp=Get_hash(st,le);
                        mp[tmp]++;
                    }
                    i++;//当前位置存在大于三的回文串,避免覆盖后移一位。
                }
            }
            if(mp.size()>=2) printf("%s
    ",s);
        }
        return 0;
    }
  • 相关阅读:
    Android学习之Android studio TraceView和lint工具的使用具体解释
    Caffe + Ubuntu 15.04 + CUDA 7.0 安装以及配置
    web安全之渗透测试
    屏蔽alert弹框下面一层的操作
    org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:
    java.lang.NoClassDefFoundError
    20 道 Spring Boot 面试题
    java节假日api--关于节假日想到的
    CSVWriter生成文件时writer.writeRecord();方法保存的文件末尾多一个空行
    git思维导图
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13033783.html
Copyright © 2011-2022 走看看