hdu2243 The road to postgraduate entrance examination is vast-word complex [kuangbin topic-ac automata]

Before doing this, it is recommended to do poj2778.
Poj2778
is similar to poj2778. It is to find the number of strings with length n without pattern strings. This problem is to include at least one, so it is very simple. Find the total. Then subtract the number without pattern strings.

There are some details to pay attention to. First of all, the mod of this question is 2^64, so we can open the data to ull. Then, to calculate the total number, the fast power of the matrix is ​​also needed, and the time complexity of linear recursion is also unacceptable. In addition, this question also involves summation, so one dimension needs to be added to the state transition matrix, and the L+1th column is all ones.

#include <bits/stdc++.h>
#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 = 10000*50;
//const int mod = 100000;
const int Size = 110;

struct Marix{
    
    
    ll a[Size][Size];
    ll n;
    Marix(){
    
    
        n = Size;
        memset(a, 0, sizeof(a));
    }
    Marix(ll _n)
    {
    
    
        n = _n;
        for (int i = 0; i < n; i++)
        {
    
    
            for (int j = 0; j < n; j++)
                a[i][j] = 0;
        }
    }
    Marix operator * (const Marix &A){
    
    
        Marix B = Marix(A.n);
        for(int k = 0; k < A.n; ++k){
    
    
            for(int i = 0; i < A.n; ++i){
    
    
                for(int j = 0; j < A.n; ++j){
    
    
                    B.a[i][j] = (B.a[i][j] + (a[i][k]*A.a[k][j] ) ) ;
                }
            }
        }
        return B;
    }
};
Marix mul(Marix a,Marix b){
    
    //矩阵乘法
    Marix res=Marix(a.n);
    for(int i=0;i<a.n;i++){
    
    
        for(int j=0;j<a.n;j++){
    
    
            for(int k=0;k<a.n;k++){
    
    
                ll tmp=a.a[i][k]*b.a[k][j];
                res.a[i][j]=(res.a[i][j]+tmp);
            }
        }
    }
    return res;
}

Marix powMod(Marix A, ll cnt){
    
    
    Marix res = Marix(A.n);
    for(int i = 0; i < A.n; ++i)res.a[i][i] = 1;
    while(cnt){
    
    
        if(cnt&1)res = mul(res,A);
        //cout << res.a[0][1] << endl;
        A = mul(A,A);
        cnt >>= 1;
    }
    return res;
}


const int maxnode = 26;
int ch[maxn][maxnode]; //字典树
int cnt[maxn];    //单词出现次数
int sz;
int fail[maxn];
//map<char,int> mp;
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;
}
void insert(char str[], int len) //插入字符串
{
    
    
    int u = 0;
    per(i, 0, len)
    {
    
    
        int v = str[i]-'a';
        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]];
    }
}

Marix getmatrix()
{
    
    
    Marix ma = Marix(sz+1);
    per(i,0,sz)
    {
    
    
        per(j,0,maxnode)
        {
    
    
            if(cnt[ch[i][j]]==1)continue;
            ma.a[i][ch[i][j]]++;
        }
    }
    for(int i=0;i<sz+1;i++){
    
    //再多开一维,使得第id+1列全都置为1
        ma.a[i][sz]=1;
    }
    return ma;
}
char s[20];
int main()
{
    
    

    #ifndef ONLINE_JUDGE
        int startTime = clock();
        FIN;
    #endif
    //fastio;
	//忘记初始化是小狗
    //freopen("out.txt","w",stdout);
    //ios::sync_with_stdio(false);
    int n,m;
    //cout << id('0');
    while(~scanf("%d%d",&n,&m)){
    
    
        init();
        per(i,0,n)
        {
    
    
            scanf("%s",s);
            insert(s,strlen(s));
        }
        getfail();
        Marix mm = getmatrix();
//        per(i,0,sz)
//        {
    
    
//            per(j,0,sz)cout << mm.a[i][j] << ' ';
//            cout << endl;
//        }
        Marix r1 = powMod(mm,m);
        ll res = 0,ans = 0;
        per(i,0,sz+1)res = (res+r1.a[0][i]);
        res--;
        Marix r2 = Marix(2);
        r2.a[0][0] = 26,r2.a[0][1] = r2.a[1][1] = 1;
        Marix r3 = powMod(r2,m);
        ans = r3.a[0][0]+r3.a[0][1];
        ans--;
        cout << ans-res << endl;
        //cout << ans-1 << endl;
    }
    #ifndef ONLINE_JUDGE
        printf("\nTime = %dms\n", clock() - startTime);
    #endif
    return 0;
}


Guess you like

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