<span>HDU5763 Another Meaning(KMP+dp)</span>

题意:

给你一个主串一个子串,然后主串中匹配到子串就可以把当前部分改为*,

问主串有多少中不同的样子

思路:

先KMP预处理主串中所有匹配到子串的末尾位置

然后用dp

dp[N][2]只更新成功匹配的末尾位置

其中dp[i][0]保存当前位置不参与改变*的总情况

dp[i][1]保存当前位置参与改变*的总情况

用一个变量tmp保存这段长度(除了当前位置的l-1长度)中所有的dp[i][1]的和

可以容易的推出dp[i][0]=tmp+dp[i][1]

dp[i][1]=不在当前l长度中的前一个匹配到的位置的dp[0]+dp[1](最小为1)

附上凌乱的代码。。

/* ***********************************************
Author        :devil
************************************************ */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 1e5+5;
const int M = 1e5+5;
const int INF = 0x3f3f3f3f;
const LL mod = 1e9+7;
int Next[M],l;
LL dp[N][2];
char T[N],P[M];
bool yes[N];
void MakeNext(int m)
{
    Next[0]=-1;
    int i=0,j=-1;
    while(i<m)
    {
        if(j==-1||P[i]==P[j])
        {
            ++i,++j;
            Next[i]=j;
        }
        else j=Next[j];
    }
}
int KMP(int n,int m)
{
    MakeNext(m);
    int i=0,j=0,ret=0;
    while(i<n)
    {
        if(T[i]==P[j]||j==-1)++i,++j;
        else j=Next[j];
        if(j==m)
        {
            ++ret;
            yes[i]=1;
            j=Next[j];//可以记录重复的
            /*j=0;//不记录重复的*/
        }
    }
    return ret;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int n,m,kase;
    scanf("%d",&kase);
    for(int q=1;q<=kase;q++)
    {
        l=0;
        scanf("%s%s",T,P);
        n=strlen(T),m=strlen(P);
        memset(dp,0,sizeof(dp));
        memset(yes,0,sizeof(yes));
        LL cnt=KMP(n,m);
        LL ans=1;
        LL tmp=0;
        int pre=0,ansp=0;
        for(int i=m;i<=n;i++)
        {
            if(yes[i-m])
            {
                tmp-=dp[i-m][1];
                while(tmp<0) tmp+=mod;
                pre=i-m;
            }
            if(yes[i])
            {
                ansp=i;
                dp[i][1]=max(dp[pre][0]+dp[pre][1],1ll)%mod;
                dp[i][0]=(tmp+dp[i][1])%mod;
                tmp=(tmp+dp[i][1])%mod;
            }
            //printf("%d %d %d %lld %lld\n",i,pre,yes[i],dp[i][0],dp[i][1]);
        }
        printf("Case #%d: %I64d\n",q,ansp?(dp[ansp][0]+dp[ansp][1])%mod:1);
    }
    return 0;
}

 

全部评论

相关推荐

刚刷到字节跳动官方发的消息,确实被这波阵仗吓了一跳。在大家还在纠结今年行情是不是又“寒冬”的时候,字节直接甩出了史上规模最大的转正实习计划——ByteIntern。咱们直接看几个最硬的数,别被花里胡哨的宣传词绕晕了。首先是“量大”。全球招7000多人是什么概念?这几乎是把很多中型互联网公司的总人数都给招进来了。最关键的是,这次的资源分配非常精准:研发岗给了4800多个Offer,占比直接超过六成。说白了,字节今年还是要死磕技术,尤其是产品和AI领域,这对于咱们写代码的同学来说,绝对是今年最厚的一块肥肉。其次是大家最关心的“转正率”。官方直接白纸黑字写了:整体转正率超过50%。这意味着只要你进去了,不划水、正常干,每两个人里就有一个能直接拿校招Offer。对于2027届(2026年9月到2027年8月毕业)的同学来说,这不仅是实习,这简直就是通往大厂的快捷通道。不过,我也得泼盆冷水。坑位多,不代表门槛低。字节的实习面试出了名的爱考算法和工程实操,尤其是今年重点倾斜AI方向,如果你简历里有和AI相关的项目,优势还是有的。而且,转正率50%也意味着剩下那50%的人是陪跑的,进去之后的考核压力肯定不小。一句话总结:&nbsp;27届的兄弟们,别犹豫了。今年字节这是铁了心要抢提前批的人才,现在投递就是占坑。与其等到明年秋招去千军万马挤独木桥,不如现在进去先占个工位,把转正名额攥在手里。
喵_coding:别逗了 50%转正率 仔细想想 就是转正与不转正
字节7000实习来了,你...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务