HDU-5763 Another Meaning

题意:t组询问,每次给出串\(a,b\),串\(a\)中与\(b\)相等的字串可以替换为\(*\),问a可以变为多少种字符串。

KMP+DP,从前往后\(dp\)\(a\)的每一个位置,设枚举到\(i\),如果$a[i-len(b) $ ~ $ i]==b\(,那么我们就可以选择是否将这个字串替换,答案就等于不替换的方案数(\)f[i-1]\()加替换的方案数(\)f[i-len(b)]$)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+100,P=1e9+7;
int n,m,t,nex[maxn],ok[maxn],k,f[maxn];
char a[maxn],b[maxn];
void getnex(){
    nex[1]=0,k=0;
    for(int i=2;i<=n;i++){
        while(k>0&&b[k+1]!=b[i])
            k=nex[k];
        if(b[k+1]==b[i])
            k++;
        nex[i]=k;
    }
}
int main(){
    scanf("%d",&t);
    for(int o=1;o<=t;o++){
        scanf("%s%s",a+1,b+1);
        n=strlen(a+1),m=strlen(b+1);
        memset(ok,0,sizeof(ok));
        getnex();
        for(int i=0,j=0;i<=n;i++){
            if(j>0&&a[i+1]!=b[j+1])
                j=nex[j];
            if(a[i+1]==b[j+1])
                j++;
            if(j==m){
                ok[i+1]=1;
                j=nex[j];
            }
        }
        f[0]=1;
        for(int i=1;i<=n;i++){
            f[i]=f[i-1];
            if(ok[i])
                f[i]+=f[i-m],f[i]%=P;
                //这里可以让f[i]+=1,前面f[0]=0,
                //后面输出f[n]+1,不知道为什么能对?
        }
        printf("Case #%d: %d\n",o,f[n]);
    }
}

猜你喜欢

转载自www.cnblogs.com/nianheng/p/9905633.html
今日推荐