poj1625 Censored! [kuangbin topic-ac automata]

A bit malignant question...
This question is also to find the number of strings of length m without several strings, but the data will exceed longlong, so the previous matrix fast exponentiation method cannot be done, and it can only be done with dp.
The combination of ac automata and dp is very frequent, so let's start.


#include <iostream>
#include <cstdio>
#include <queue>
#include <map>
#include <cstring>
#define fi first
#define se second
#define FIN freopen("in.txt","r",stdin)
#define FIO freopen("out.txt","w",stdout)
#define INF 0x3f3f3f3f
#define per(i,a,n) for(int i = a;i < n;i++)
#define rep(i,a,n) for(int i = n;i > a;i--)
#define pern(i,a,n) for(int i = a;i <= n;i++)
#define repn(i,a,n) for(int i = n;i >= a;i--)
#define fastio std::ios::sync_with_stdio(false)
#define all(a) a.begin(), a.end()
#define ll unsigned long long
#define pb push_back
#define endl "\n"
#define pii pair<int,int>
#define sc(n) scanf("%d", &n)
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
template<typename T> inline void _max(T &a,const T b){
    
    if(a<b) a = b;}
template<typename T> inline void _min(T &a,const T b){
    
    if(a>b) a = b;}
using namespace std;
//inline ll read(){
    
    
//    ll a=0;int f=0;char p=getchar();
//    while(!isdigit(p)){f|=p=='-';p=getchar();}
//    while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=getchar();}
//    return f?-a:a;
//}
const int maxn = 1000;

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 dp[55][110];

const int maxnode = 51;
int ch[maxn][maxnode]; //字典树
int cnt[maxn];    //单词出现次数
int sz;
int fail[maxn];
map<char,int> mp;
int idx = 0;
void init()
{
    
    
    //mp['A'] = 0,mp['C']=1,mp['T']=2,mp['G']=3;
    sz = 1;
    memset(ch[0], 0, sizeof(ch[0]));
    memset(cnt,0,sizeof(cnt));
    //val[0] = 0;
    cnt[0] = 0;
}
int id(char c)
{
    
    
    if(!mp.count(c))mp[c] = idx++;
    else return mp[c];
}
void insert(char str[], int len) //插入字符串
{
    
    
    int u = 0;
    per(i, 0, len)
    {
    
    
        int v = id(str[i]);
        if (!ch[u][v])
        {
    
    
            memset(ch[sz], 0, sizeof(ch[sz]));
            //val[sz] = 0;
            cnt[sz] = 0;
            ch[u][v] = sz++;
        }
        u = ch[u][v];
    }
    cnt[u]=1;
    //在这里我们可以建立一个int-string的映射,以通过节点序号得知这个点是哪个单词的结尾
}

void getfail()
{
    
    
    //所有模式串已插入完成
    queue<int> q;
    per(i, 0,maxnode)
    {
    
    
        if (ch[0][i])
        {
    
    
            fail[ch[0][i]] = 0;
            q.push(ch[0][i]);
        }
    }
    while (!q.empty())
    {
    
    
        int now = q.front();
        q.pop();
        per(i, 0, maxnode)
        {
    
    
            if (ch[now][i])
            {
    
    
                fail[ch[now][i]] = ch[fail[now]][i];
                q.push(ch[now][i]);
            }
            else
                ch[now][i] = ch[fail[now]][i];
        }
        cnt[now] |= cnt[fail[now]];
    }
}


char s[100];
int main()
{
    
    

//    #ifndef ONLINE_JUDGE
//        int startTime = clock();
//        FIN;
//    #endif
    //fastio;
	//忘记初始化是小狗
    //freopen("out.txt","w",stdout);
    //ios::sync_with_stdio(false);
    int n,m,p;
    //cout << id('0');
    while(~scanf("%d%d%d",&n,&m,&p)){
    
    
        init();
        scanf("%s",s);
        per(i,0,n)id(s[i]);
        per(i,0,p)
        {
    
    
            scanf("%s",s);
            insert(s,strlen(s));
        }
        getfail();
        dp[0][0].set(1);
        pern(i,1,m)
        {
    
    
            per(j,0,sz)
            {
    
    
                per(k,0,n)
                {
    
    
                    int v = ch[j][k];
                    if(!cnt[v]) dp[i][v] = dp[i][v]+dp[i-1][j];
                }
            }
        }
        BigInteger res;
        //res.print();
        per(i,0,sz)res = res+dp[m][i];
        res.print();
    }
//    #ifndef ONLINE_JUDGE
//        printf("\nTime = %dms\n", clock() - startTime);
//    #endif
    return 0;
}


Guess you like

Origin blog.csdn.net/qq_39586345/article/details/108535995