码迷,mamicode.com
首页 > 其他好文 > 详细

無名(noname) 字符串

时间:2017-08-23 19:12:51      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:amp   cells   fine   double   scanf   open   print   strlen   can   

【问题描述】

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

题意很简单,给你一个串,求他有多少个不同的子串,满足前缀为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\n",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\n",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\n",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\n",i,j); 
            if(qian[i]&&hou[j]&&j-i>=len1-1&&j-i>=len2-1)
            {
                ll now=find(i,j);
//                printf("now=%lld\n",now);
                if(!vis[now])
                {
                    ans++;
                    vis[now]=1;
                }
            }
        }
    printf("%d\n",ans);
    return 0;
}

 

無名(noname) 字符串

标签:amp   cells   fine   double   scanf   open   print   strlen   can   

原文地址:http://www.cnblogs.com/gshdyjz/p/7419601.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!