考研路茫茫--单词情结

分析:与poj的2778差不多的,求出来所有的情况然后减去不包含的就行了,这次使用了一下kuangbin的那种自动机写法,确实还不错,因为尤是在建立矩阵的时候更加方便。

 
代码如下:
===============================================================================================================================
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;

const int MAXN = 107;
const int MAXM = 26;
const int mod  = 100000;

struct Matrix
{///定义矩阵
    int size;
    unsigned long long edge[MAXN][MAXN];

    Matrix(int Len)
    {
        size = Len;
        memset(edge, false, sizeof(edge));
    }
    Matrix operator *(const Matrix &Map) const
    {
        Matrix ans(size);

        for(int i=0; i<size; i++)
        for(int j=0; j<size; j++)
        for(int k=0; k<size; k++)
        {
            ans.edge[i][j] += edge[i][k] * Map.edge[k][j];
        }

        return ans;
    }
};

struct Ac_Trie
{
    int next[MAXN][MAXM];
    int fail[MAXN], End[MAXN];
    int Len, root;

    Ac_Trie()
    {
        memset(next, -1, sizeof(next));
        memset(End, false, sizeof(End));
        Len = 1, root = 0;
    }

    void Insert(char s[])
    {
        int p = root;

        for(int i=0; s[i]; i++)
        {
            int k = s[i] - 'a';

            if(next[p][k] == -1)
                next[p][k] = Len++;
            p = next[p][k];
        }

        End[p] = true;
    }

    void GetFail()
    {
        queue<int> Q;
        int p = root;

        fail[p] = root;

        for(int i=0; i<MAXM; i++)
        {
            if(next[p][i] == -1)
                next[p][i] = root;
            else
            {
                fail[next[p][i]] = root;
                Q.push(next[p][i]);
            }
        }

        while(Q.size())
        {
            p = Q.front();
            Q.pop();

            for(int i=0; i<MAXM; i++)
            {
                if(next[p][i] == -1)
                    next[p][i] = next[fail[p]][i];
                else
                {
                    fail[next[p][i]] = next[fail[p]][i];
                    Q.push(next[p][i]);
                }
            }

            End[p] |= End[fail[p]];
        }
    }

    Matrix GetMatrix()
    {
        Matrix ans(Len+1);

        for(int i=0; i<Len; i++)
        for(int k=0; k<MAXM; k++)
        {
            if(End[next[i][k]] == false)
                ans.edge[i][next[i][k]] += 1;
        }

        for(int i=0; i<=Len; i++)
            ans.edge[i][Len] = 1;

        return ans;
    }
};

Matrix QuickPow(long long K, Matrix Map)
{
    Matrix ans(Map.size);

    for(int i=0; i<ans.size; i++)
        ans.edge[i][i] = 1;

    while(K)
    {
        if(K & 1)
            ans = ans * Map;
        Map = Map * Map;

        K /= 2;
    }

    return ans;
}

int main()
{
    long long N, L;

    while(scanf("%lld%lld", &N, &L) != EOF)
    {
        char s[MAXN];
        Ac_Trie a;

        while(N--)
        {
            scanf("%s", s);
            a.Insert(s);
        }

        a.GetFail();
        Matrix ans = a.GetMatrix();

        unsigned long long sum1=0, sum=0;

        ans = QuickPow(L, ans);

        for(int i=0; i<ans.size; i++)
            sum1 += ans.edge[0][i];

        ans.size = 2;
        ans.edge[0][0] = 26;
        ans.edge[1][0] = 0;
        ans.edge[0][1] = ans.edge[1][1] = 1;

        ans = QuickPow(L, ans);

        sum = ans.edge[0][1] + ans.edge[0][0];

        cout << sum - sum1 <<endl;
    }

    return 0;
}
原文地址:https://www.cnblogs.com/liuxin13/p/4754995.html