• 無名(noname) 字符串


    【问题描述】

    因为是蒯的题所以没想好名字,为什么要用繁体呢?去看《唐诗三百首》吧!

    题意很简单,给你一个串,求他有多少个不同的子串,满足前缀为A,后缀为B。

    需要注意的是,串中所有的字母都是小写字母。

    友情提示:如果你过不了样例,请注意是不同的子串。                    

    【输入文件】

    一共3行。

    第一行母串S;

    第二行串A;

    第三行串B。

    【输出文件】

       一个数,即有多少不同的子串。

    【输入样例】

    abababab

    a

    b

    【输出样例】

    4

    【数据规模和约定】

    100%:

    length(S)<=2000;

    length(A)<=2000;

    length(B)<=2000;

    30%:都少个0。


    首先我们可以枚举子串是吧,这样首先就来了一个n^2的复杂度,然后我们判断前缀和后缀,这些其实没什么太难的部分,我们只要先预处理是否是前缀和后缀,就可以很方便的解决了。

    然后问题来了,我们怎么在字符串上判重呢?

    这里我们就要引入字符串hash了。

    我们把S字符串从0到i的字符串hash止记录在hash【i】中,然后我们就可以得到前缀的字符串hash了。

    hash[i]=(hash[i-1]*p+S[i]-'a'+1)%t;

    那么其它位怎么表示呢?

    我们可以令字符串S【i】~S[j]=(hash[j]-hash[i-1]*p^(j-i+1))%t;(这里p的次方可以首先求好存好)。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define il inline
    #define db double
    using namespace std;
    ll p=31,t=100000007;
    ll hash[2045];
    bool vis[100000045];
    ll ci[2045];
    il ll find(int x,int y)
    {
        return (hash[y]+t-hash[x-1]*ci[y-x+1]%t)%t;
    }
    bool qian[2045];
    bool hou[2045];
    char S[2045];
    char A[2045];
    char B[2045];
    int len,len1,len2;
    int main()
    {
        freopen("noname.in","r",stdin);
        freopen("noname.out","w",stdout);
        ci[0]=1;
        for(int i=1;i<=2000;i++)
        ci[i]=(ci[i-1]*p)%t;
        scanf("%s%s%s",S,A,B);
        len=strlen(S);
        len1=strlen(A);
        len2=strlen(B);
    //    printf("p=%lld,t=%lld
    ",p,t);
        hash[0]=S[0]-'a'+1;
        for(int i=1;i<len;i++)
        hash[i]=(hash[i-1]*p+S[i]-'a'+1)%t;
    //    for(int i=1;i<len;i++)
    //    printf("hash[i]=%lld
    ",hash[i]);
        for(int i=0;i<len-len1+1;i++)
        {
            int l=0;
            for(int j=0;j<len1;j++)
            if(S[i+j]==A[j])
            l++;
            if(l==len1)
            qian[i]=1;
        }
        for(int i=len-1;i>=len2-1;i--)
        {
            int l=0;
            for(int j=0;j<len2;j++)
            if(S[i-len2+j+1]==B[j])
            l++;
            if(l==len2)
            hou[i]=1;
        }
    //    for(int i=0;i<len;i++)
    //    printf("%d %d
    ",qian[i],hou[i]);
        int ans=0;
        for(int i=0;i<len;i++)
            for(int j=i;j<len;j++)
            {
    //                printf("i=%d j=%d
    ",i,j); 
                if(qian[i]&&hou[j]&&j-i>=len1-1&&j-i>=len2-1)
                {
                    ll now=find(i,j);
    //                printf("now=%lld
    ",now);
                    if(!vis[now])
                    {
                        ans++;
                        vis[now]=1;
                    }
                }
            }
        printf("%d
    ",ans);
        return 0;
    }
    PEACE
  • 相关阅读:
    看完一本,加油
    一个简单的动作,让你的手机号码变成空号
    Goldwave心得
    UML设计初步 基本概念一(actor, use case)
    ASP.NET控件开发 概念和HelloWorld控件
    控件的呈现
    ASP.NET控件生命周期
    ASP老项目中如何搜索一个文件在哪些地方被引用
    PL/SQL语法 游标
    2009编程语言排名
  • 原文地址:https://www.cnblogs.com/gshdyjz/p/7419601.html
Copyright © 2020-2023  润新知