归途与征程

206 篇文章 0 订阅
37 篇文章 0 订阅

Description

在这里插入图片描述
Input
第一行为字符串A。

第二行为字符串B。

Output
输出在B的所有循环同构串中,有多少个能够与A匹配。

Sample Input
输入1:

aaaa

aaaa

输入2:

a*a

aaaaaa

输入3:

abc

abacabadabacaba

Sample Output
输出1:

4

输出2:

6

输出3:

15

Data Constraint
对于30%的数据,M<=20;
对于80%的测试点,M<=200;
对于100%的测试点,1<=N<=100,1<=M<=100000。

.
.
.
.
.
.
.
分析
将B串倍长,将A串按通配符分割,分割后预处理每段在B串的匹配位置,枚举起始位置,强制要求A串首尾与起始、终止位置匹配,中间的段贪心取最左的

.
.
.
.
.
.
程序:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

int n,m,t,f[200010][60],next[200010][60],a[110],b[200010],q[110],p[110],l[110],ans=0;
char ch[100010];

void kmp(int num,int x)
{
    p[1]=0;
    int j=0;
    for (int i=2;i<=x;i++)
    {
        while (j>0&&q[j+1]!=q[i]) j=p[j];
        if (q[j+1]==q[i]) j++;
        p[i]=j;
    }
    j=0;
    for (int i=1;i<=2*m-1;i++)
    {
        while (j>0&&q[j+1]!=b[i]) j=p[j];
        if (q[j+1]==b[i]) j++;
        if (j==x) 
        {
            f[i-x+1][num]=1;
            j=p[j];
        }
    }
}

void find()
{
    t=0;
    int i=1;
    while (i<=n)
    {
        while (a[i]<0 && i<=n) i++;
        if (i>n) break;
        t++;
        l[t]=0;
        while (a[i]>=0&&i<=n)
        {
            l[t]++;
            q[l[t]]=a[i];
            i++;
        }
        kmp(t,l[t]);
    }
    for (int j=1;j<=t;j++)
    {
        next[2*m][j]=m+m;
      	for (int i=2*m-1;i>=1;i--)
    		if (f[i][j]==1) next[i][j]=i; else next[i][j]=next[i+1][j];
    }
}

int main()
{
    scanf("%s",ch);
    n=strlen(ch);
    for (int i=1;i<=n;i++)
    	a[i]=ch[i-1]-'a';
    scanf("%s",ch);
    m=strlen(ch);
    for (int i=1;i<=m;i++)
    	b[i]=ch[i-1]-'a';
    for (int i=m+1;i<=2*m-1;i++)
    	b[i]=b[i-m];
    for (int i=0;i<=25;i++)
    	f[2*m][i]=2*m;
    memset(f,0,sizeof(f));
    find();
    for (int i=1;i<=m;i++)
    {
        int ed=i+m-1,x;
        x=next[i][1];
        if (x+l[1]-1>ed) continue;
        if (a[1]>=0&&x!=i) continue;
        for (int j=2;j<=t;j++)
        	x=next[x+l[j-1]][j]; 
        if (x+l[t]-1>ed||x==0) continue;
        if (a[n]>=0&&f[ed-l[t]+1][t]!=1) continue;
        ans++;
    }
    printf("%d",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值