Censored! :ac自动机 + DP

分析

如果字符串的长度大一点可以用矩阵快速幂来做,因为数据范围比较小,可以用DP来代替
我们去枚举每一位在a自动机中的位置,再去枚举下一位的位置,判断是否打过标记,然后进行状态转移
需要注意的是,如果输入字符是负数,需要增加一个偏移量
最后需要再写一个大数

最后吐槽一句,poj的编译器真老。。。

代码


#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<int> VI;
const int INF = 0x3f3f3f3f;
const int N = 150;
const ll mod= 1000000007;
const double eps = 1e-9;
map<char,int> M;
int tr[N][52],idx;
int ne[N];
int cnt[N];
char str[N];

int q[N];
int n,m,llll;


void insert(){
    
    
    int p = 0;
    for(int i = 0;str[i];i++){
    
    
        int t = M[str[i] + 200];
        if(!tr[p][t]) tr[p][t] = ++idx;
        p = tr[p][t];
    }
    cnt[p] = 1;
}

void build(){
    
    
    int hh = 0,tt = -1;
    for(int i = 0;i < m;i++)
        if(tr[0][i])
            q[++tt] = tr[0][i];
    while(hh <= tt){
    
    
        int t = q[hh++];
        for(int i = 0;i < m;i++){
    
    
            int c = tr[t][i];
            if(!c) tr[t][i] = tr[ne[t]][i];
            else{
    
    
                ne[c] = tr[ne[t]][i];;
                cnt[c] |= cnt[ne[c]];
                q[++tt] = c;
            }
        }
    }
}
struct BigInteger{
    
    
    int A[25];
    enum{
    
    MOD = 10000};
    BigInteger(){
    
    memset(A, 0, sizeof(A)); A[0]=1;}
    void set(int x){
    
    memset(A, 0, sizeof(A)); A[0]=1; A[1]=x;}
    void print(){
    
    
        printf("%d", A[A[0]]);
        for (int i=A[0]-1; i>0; i--){
    
    
            if (A[i]==0){
    
    printf("0000"); continue;}
            for (int k=10; k*A[i]<MOD; k*=10) printf("0");
            printf("%d", A[i]);
        }
        printf("\n");
    }
    int& operator [] (int p) {
    
    return A[p];}
    const int& operator [] (int p) const {
    
    return A[p];}
    BigInteger operator + (const BigInteger& B){
    
    
        BigInteger C;
        C[0]=max(A[0], B[0]);
        for (int i=1; i<=C[0]; i++)
            C[i]+=A[i]+B[i], C[i+1]+=C[i]/MOD, C[i]%=MOD;
        if (C[C[0]+1] > 0) C[0]++;
        return C;
    }
    BigInteger operator * (const BigInteger& B){
    
    
        BigInteger C;
        C[0]=A[0]+B[0];
        for (int i=1; i<=A[0]; i++)
            for (int j=1; j<=B[0]; j++){
    
    
                C[i+j-1]+=A[i]*B[j], C[i+j]+=C[i+j-1]/MOD, C[i+j-1]%=MOD;
            }
        if (C[C[0]] == 0) C[0]--;
        return C;
    }
};

BigInteger f[N][N];

int main(){
    
    
    scanf("%d%d%d",&m,&n,&llll);
    scanf("%s",str);
    for(int i = 0;i < m;i++){
    
    
        M[str[i] + 200] = i;
    }
    while(llll--){
    
    
        scanf("%s",str);
        insert();
    }
    build();
    f[0][0].set(1);
    for(int i = 1;i <= n;i++)
        for(int j = 0;j <= idx;j++){
    
    
            if(cnt[j]) continue;
            for(int k = 0;k < m;k++){
    
    
                int tj = tr[j][k];
                if(cnt[tj]) continue;
                f[i][tj] = f[i][tj] + f[i - 1][j];
            }
        }
    BigInteger res;
    for(int i = 0;i <= idx;i++) res = res + f[n][i];
    res.print();
    return 0;
}

/**
*  ┏┓   ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃       ┃
* ┃   ━   ┃ ++ + + +
*  ████━████+
*  ◥██◤ ◥██◤ +
* ┃   ┻   ┃
* ┃       ┃ + +
* ┗━┓   ┏━┛
*   ┃   ┃ + + + +Code is far away from  
*   ┃   ┃ + bug with the animal protecting
*   ┃    ┗━━━┓ 神兽保佑,代码无bug 
*   ┃        ┣┓
*    ┃        ┏┛
*     ┗┓┓┏━┳┓┏┛ + + + +
*    ┃┫┫ ┃┫┫
*    ┗┻┛ ┗┻┛+ + + +
*/


猜你喜欢

转载自blog.csdn.net/tlyzxc/article/details/113826510