HihoCoder - 1807:好的数字串 (KMP DP)

Posted hua-dong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HihoCoder - 1807:好的数字串 (KMP DP)相关的知识,希望对你有一定的参考价值。

Sample Input

6 1212

Sample Output

298

给定一个数字字符串S,如果一个数字字符串(只包含0-9,可以有前导0)中出现且只出现1次S,我们就称这个字符串是好的。  

例如假设S=666,则1666、03660666是好的,6666、66、123不是好的;假设S=1212,则01212、12123是好的,121212、121是不好的。

请你计算长度为N的数字字符串中,有多少个是好的。由于总数可能很大,你只需要输出总数模1000000007的余数。

Input

一个整数N和一个数字串S。  

对于30%的数据,1 ≤ N ≤ 8  

对于100%的数据,1 ≤ N ≤ 1000,1 ≤ |S| ≤ N。

Output

一个整数代表答案。

 

思路:dp[i][j][k],表示前i位,而且当前尾巴与S的前缀的最长公共长度位j,k表示是否出现过S。 对于第i位,枚举0到9,并且用KMP找到最长公共部分。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1010;
const int Mod=1e9+7;
int a[maxn],dp[maxn][maxn][2],ans,N,L;
int Next[maxn]; char c[maxn];
void KMP()
{
    for(int i=2,k=0;i<=L;i++){
        while(k&&a[i]!=a[k+1]) k=Next[k];
        if(a[i]==a[k+1]) k++; Next[i]=k;
    }
}
int get(int i,int j)
{
    while(1){
        if(a[i+1]==j) return i+1;
        if(i==0) break; i=Next[i];
    }return 0;
}
int main()
{
    scanf("%d%s",&N,c+1); L=strlen(c+1); a[L+1]=-1;
    rep(i,1,L) a[i]=c[i]-0; dp[0][0][0]=1;
    KMP();
    rep(i,1,N){
        rep(j,0,min(i-1,L)){
            rep(k,0,9) {
                int t=get(j,k);
                if(j==L-1){
                    if(t==L) (dp[i][t][1]+=dp[i-1][j][0])%=Mod;
                    else {
                        (dp[i][t][1]+=dp[i-1][j][1])%=Mod;
                        (dp[i][t][0]+=dp[i-1][j][0])%=Mod;
                    }
                }
                else {
                    if(t!=L) (dp[i][t][1]+=dp[i-1][j][1])%=Mod;
                    (dp[i][t][0]+=dp[i-1][j][0])%=Mod;
                }
            }
        }

    }
    rep(i,0,L) (ans+=dp[N][i][1])%=Mod;
    printf("%d
",ans);
    return 0;
}

 

以上是关于HihoCoder - 1807:好的数字串 (KMP DP)的主要内容,如果未能解决你的问题,请参考以下文章

HihoCoder - 1445 后缀自动机 试水题

HihoCoder1663双阶乘的末尾数字([Offer收割]编程练习赛40)(暴力||数学)

hihocoder 编程练习赛23

hihoCoder#1384 : Genius ACM

hihoCoder #1349 Nature Numbers

[hihocoder][Offer收割]编程练习赛58