zoukankan      html  css  js  c++  java
  • HIT暑期集训 字符串

    一个网上找到关于马拉车算法的博客

    https://www.jianshu.com/p/392172762e55

    B    CodeForces 1056E

    做法是枚举0串代表的字符串的长度,由这个长度可以推出1串代表的字符串长度,接着按照给出的01串的顺序检查每个0串,每个1串对应的字符串是否都分别相等(用hash)。若检查无误则答案加一。

    做法复杂度很迷,并且hash也很迷,或许写双哈希会好一点,但是我太懒了就。。。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 1000005
    #define mod 10000007
    #define P 131
    using namespace std;
    typedef long long ll;
    int lena,lenb,ans,cnt[2];
    ll pw[maxn],f[maxn],ha[2];
    char a[maxn],b[maxn];
    void prework()
    {
        int i;
        f[0]=0;pw[0]=1;
        for (i=1;i<=lenb;i++)
        {
            f[i]=(f[i-1]*P+(b[i]-'a'+1))%mod;
            pw[i]=pw[i-1]*P%mod;
        }
    }
    ll Hash(int l,int r)
    {
        return (f[r]-f[l-1]*pw[r-(l-1)]%mod+mod)%mod;//我没学过的hash方法。。 
    }
    int main()
    {
        int i,l,r,num0,num1,l0,l1,flag;
        ll tmp;
        scanf("%s%s",a+1,b+1);
        lena=strlen(a+1);
        lenb=strlen(b+1);
        for (i=1;i<=lena;i++) cnt[a[i]-'0']++;
        prework();
        for (l0=1;l0<lenb;l0++)//枚举0串长度
        {
            if (l0*cnt[0]>=lenb) break;//所有0串长度之和大于等于b串,退出 
            if ((lenb-l0*cnt[0])%cnt[1]!=0) continue;
            l1=(lenb-l0*cnt[0])/cnt[1];//1串长度 
            flag=1;
            ha[0]=-1;ha[1]=-2;
            num0=0;num1=0;//已经检查过的0/1数
            
            for (i=1;i<=lena;i++)
            {
                if (a[i]=='0')
                {
                    l=num0*l0+num1*l1+1;//当前串的开始位置
                    r=l+l0-1;//结束位置
                    num0++;
                    tmp=Hash(l,r);
                    if (ha[0]==-1) ha[0]=tmp;
                    else if (ha[0]!=tmp)
                    {
                        flag=0;break;
                    }
                }
                else if (a[i]=='1')
                {
                    l=num0*l0+num1*l1+1;//当前串的开始位置
                    r=l+l1-1;//结束位置
                    num1++;
                    tmp=Hash(l,r);
                    if (ha[1]==-2) ha[1]=tmp;
                    else if (ha[1]!=tmp)
                    {
                        flag=0;break;
                    } 
                }
                if (ha[0]==ha[1])
                {
                    flag=0;break;
                }
            }
            if (flag && ha[0]!=ha[1]) ans++;
        }
        printf("%d",ans);
        return 0;
    }
    View Code

    C    HDU 4300

    把给出的密文+明文的a串全当作密文,翻译成明文得到新串b。可以发现a后面的明文部分会与b的前面由密文翻译而来的明文部分有公共前缀。所以将ab进行匹配,匹配出的字符串在a串中的起点位置之前的就是密文。注意匹配时要从a串中间开始匹配。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 100100
    using namespace std;
    int p[maxn];
    char a[maxn],b[maxn],c[maxn],d[maxn];
    void prework(int len)
    {
        p[0]=-1;
        int i,j=-1;
        for (i=1;i<len;i++)
        {
            while (j>=0 && b[j+1]!=b[i]) j=p[j];
            if (b[j+1]==b[i]) j++;
            p[i]=j;
        }
    } 
    int work(int lim,int len)
    {
        p[0]=-1;
        int i,j=-1;
        for (i=lim;i<len;i++)
        {
            while (j>=0 && b[j+1]!=a[i]) j=p[j];
            if (b[j+1]==a[i]) j++;
        }
        return j;
    }
    int main()
    {
        int t,i,j,k,len,lc,lim,re;
        scanf("%d",&t);
        while (t--)
        {
            memset(p,0,sizeof(p));
            scanf("%s%s",c,a);
            lc=strlen(c);
            len=strlen(a);
            for (i=0;i<lc;i++) d[c[i]-'a']=i+'a';
            for (i=0;i<len;i++) b[i]=d[a[i]-'a'];
            prework(len);
            lim=(len+1)/2;
            re=work(lim,len);
            for (i=0;i<len-re-1;i++) printf("%c",a[i]);
            for (i=0;i<len-re-1;i++) printf("%c",b[i]);
            printf("
    ");
        }
        return 0;
    }
    View Code

    D    HDU 4821

    E    HDU 5340

    跑一遍马拉车,枚举第一个和第三个回文串,检查中间剩下的是不是回文串。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 40005
    #define inf 99999999;
    using namespace std;
    int p[maxn],len,cnt1,cnt2,q1[maxn],q2[maxn];
    char a[maxn],s[maxn];
    void manacher()
    {
        int mx=0,id,i;
        for (i=1;i<len;i++)
        {
            if (mx>i) p[i]=min(p[2*id-i],mx-i);
            else p[i]=1;
            while (s[i+p[i]]==s[i-p[i]]) p[i]++;
            if (i+p[i]>mx)
            {
                id=i;
                mx=i+p[i];
            }
        }
    }
    int main()
    {
        int t,i,j,x,y,ans,mid;
        scanf("%d",&t);
        while (t--)
        {
            scanf("%s",a);
            cnt1=0;cnt2=0;ans=0;
            memset(p,0,sizeof(p));
            len=strlen(a);
            for (i=0;i<len;i++) 
            {
                s[i*2+1]=a[i];
                s[i*2+2]='#';
            }
            len=len*2;
            s[0]='$';
            s[++len]='@';
            manacher();
            for (i=1;i<len-1;i++)
            {
                if (i-p[i]==0) q1[++cnt1]=i+p[i];
                if (i+p[i]==len) q2[++cnt2]=i-p[i];
            }
            for (i=1;i<=cnt1;i++)
            for (j=1;j<=cnt2;j++)
            {
                x=q1[i];y=q2[j];
                if (x>=y) continue;
                mid=(x+y+1)/2;
                if (mid-p[mid]<=x && mid+p[mid]>=y)
                {
                    ans=1;break;
                }
            }
            if (ans) printf("Yes
    ");
            else printf("No
    ");
        }
        return 0;
    }
    View Code

    F    CodeForces 17E

  • 相关阅读:
    POJ 3126 Prime Path
    POJ 2429 GCD & LCM Inverse
    POJ 2395 Out of Hay
    【Codeforces 105D】 Bag of mice
    【POJ 3071】 Football
    【POJ 2096】 Collecting Bugs
    【CQOI 2009】 余数之和
    【Codeforces 258E】 Devu and Flowers
    【SDOI 2010】 古代猪文
    【BZOJ 2982】 combination
  • 原文地址:https://www.cnblogs.com/lsykk/p/13457058.html
Copyright © 2011-2022 走看看