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

  • 相关阅读:
    iOS 9之适配ATS(转载)
    ios8 tableView设置滑动删除时 显示多个按钮
    PHP IDE phpstorm 快捷键
    ld: warning: directory not found for option 去掉警告的方法
    iOS 评论APP撰写评论
    集成IOS 环信SDK
    iOS Xcode7免证书真机调试
    iOS定时器
    配置安装CocoPods后进行 项目基本配置
    事务的概念
  • 原文地址:https://www.cnblogs.com/lsykk/p/13457058.html
Copyright © 2011-2022 走看看