zoukankan      html  css  js  c++  java
  • ac自动机小结

    1.hdu3247

    用ac自动机预处理出所有文本串到文本串的安全距离(即不通过病毒串)

    说下为什么不加bfs部分的注释部分,因为他会导致所求的距离不是安全距离,而之所以能保证bfs的正确是因为如果两文本串连接会通过病毒部分的话,那么next一定会先到病毒部分,(因为病毒部分一定是在两个文本串之间会导致next一定优先指向病毒串)比如当前串遍历完了接下来会有01两种选择,如果走零一定会走到病毒串,那就得老老实实走1.

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxa = 60000;
    const int cha = 2;
    int dp[10][1024];
    int dis[10][maxa];
    int point[10];
    int n, m, k;
    int leng[10];
    struct Tire{
        int next[maxa][cha], fail[maxa], end[maxa];
        int root, L;
        int newnode(){
            for(int i = 0; i < cha; i++){
                next[L][i] = -1;
            }
            end[L++] = 0;
            return L-1;
        }
        void init(){
            L = 0;
            root = newnode();
        }
        int insert(char buf[], int ii){
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++){
                int x = buf[i] -'0';
                if(next[now][x] == -1)
                    next[now][x] = newnode();
                now = next[now][x];
                //printf("%d ", now);
            }//puts("");
            end[now] = ii;
            return now;
        }
        void build(){//printf("build
    ");
            queue<int>Q;
            fail[root] = root;
            for(int i = 0; i < cha; i++){
                if(next[root][i] == -1)
                    next[root][i] = root;
                else{
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while(!Q.empty()){
                int now = Q.front();
                Q.pop();
                end[now] |= end[fail[now]];
                for(int i = 0; i < cha; i++){
                    if(next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else{
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                       // printf("**%d %d
    ",next[now][i],next[fail[now]][i]);
                    }
                }
            }
        }
        void bfs(int ii){//printf("bfs
    ");
            queue<int> que;
            int vis[maxa];
            memset(vis, 0, sizeof(vis));
            que.push(point[ii]);
            vis[0] = 1;
            dis[ii][point[ii]] = 0;
            while(!que.empty()){
                int now = que.front(); que.pop();//printf("%d %d
    ", dis[ii][now], now);
                for(int i =0; i < 2; i++){
                    int Next = next[now][i];
                    if(vis[Next] == 0 && end[Next] != -1){
                        dis[ii][Next] = dis[ii][now] +1;
                        vis[Next] = 1;
                        que.push(Next);
                    }
                    /*Next = fail[Next];
                    while(Next){
                        if(vis[Next] == 0 && end[Next] != -1){
                            dis[ii][Next] = dis[ii][now] +1;
                            vis[Next] = 1;
                            que.push(Next);
                        }
                        Next = fail[Next];
                    }*/
                }
            }
        }
        int solve(){
            memset(dis, -1, sizeof(dis));
            for(int i = 0;i < n; i++){
                bfs(i);
            }//printf("solve%d %d
    ", dis[0][point[1]], dis[1][point[0]]);//printf("%d %d
    ", point[0], point[1]);
            for(int i =0 ;i  < n; i++){
                for(int k = 0; k < (1<<n); k++){
                    dp[i][k] = 10000000;
                }
            }
            for(int i = 0; i < n; i++){
                dp[i][(1<<i)] = leng[i];
            }
            for(int i =1 ;i < n; i++){
                for(int k = 0; k < n; k++){
                    for(int j = 0; j < (1<<n); j++){
                        if(dp[k][j] < 10000000){
                            for(int h = 0; h < n; h++){
                                if(!(j&(1<<h)) && dp[k][j]!=-1){
                                    dp[h][j|(1<<h)] = min(dp[h][j|(1<<h)], dp[k][j] + dis[k][point[h]]);
                                }
                            }
                        }
                    }
                }
            }
            int ans = 10000000;
            for(int i = 0; i < n; i++){
                ans = min(ans, dp[i][(1<<n)-1]);
            }
            return ans;
        }
    };
    char buf[1000005];
    Tire ac;
    int main(){
        int m;
        while(scanf("%d%d", &n, &m), n+m){
            ac.init();
            for(int i =0 ;i  < n; i++){
                scanf("%s", buf);
                leng[i] = strlen(buf);
                point[i]=ac.insert(buf, 1+i);
            }
            for(int i =0; i < m; i++){
                scanf("%s", buf);
                ac.insert(buf, -1);
            }
            ac.build();
            printf("%d
    ", ac.solve());
        }
    }
    /*
    abcdefg
    bcdefg
    cdef
    de
    e
    ssaabcdefg
    
    
    */
    View Code

    2.poj3341

    ac自动机加状压dp加广搜优化

    #include<iostream>
    #include<map>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxa = 500;
    const int cha = 4;
    int n, m, k;
    int num_[4];
    map<char, int> mp;
    /*struct point{
        short a[4];
        bool operator <(const point& b)const{
            if(a[0] != b.a[0]) return a[0] < b.a[0];
            else if(a[1] != b.a[1]) return a[1] < b.a[1];
            else if(a[2] != b.a[2]) return a[2] < b.a[2];
            else return a[3] < b.a[3];
        }
    };
    map<point, int>dp[maxa];
    map<point, bool> bo;*/
    int dp[500][11*11*11*11];
    int num[maxa];
    struct Tire{
        int next[maxa][cha], fail[maxa];
        long long end[maxa], po[maxa];
        int root, L;
        int newnode(){
            for(int i = 0; i < cha; i++){
                next[L][i] = -1;
            }
            end[L] = 0;
            num[L++] = 0;
            return L-1;
        }
        void init(){
            L = 0;
            root = newnode();
        }
        void insert(char buf[], int ii){
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++){
                int x = mp[buf[i]];
                if(next[now][x] == -1)
                    next[now][x] = newnode();
                now = next[now][x];
                //printf("%d ", now);
            }//puts("");
            long long one = 1;
            end[now] |= (one<<ii);
        }
        void build(){
            queue<int>Q;
            fail[root] = root;
            for(int i = 0; i < cha; i++){
                if(next[root][i] == -1)
                    next[root][i] = root;
                else{
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while(!Q.empty()){//printf("*");
                int now = Q.front();
                end[now] |= end[fail[now]];
                long long p = end[now];
                while(p){
                    num[now] += p%2;
                    p /= 2;
                }
                Q.pop();
               // end[now] |= end[fail[now]];
                for(int i = 0; i < cha; i++){
                    if(next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else{
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                       // printf("**%d %d
    ",next[now][i],next[fail[    now]][i]);
                    }
                }
            }
        }
        int solve(){//printf("**%d
    ", next[1][3]);
            memset(dp, -1, sizeof(dp));
            dp[0][0] = 0;
            bool vis[11*11*11*11];
            memset(vis, 0, sizeof(vis));
            queue<int>que;
            que.push(0);
            while(!que.empty()){
                int now = que.front(); que.pop();
                //printf("%d ", now);
                int wei = 1;
                for(int i =0;i < 4; i++){/*if(now==1){printf("&&
    ");
                        printf("%d %d
    ", wei, num_[i]);
                    }*/
                    if(now % (wei*(num_[i]+1)) /wei == num_[i]){
                        wei *= num_[i] +1;
                        continue;
                    }
                    int Next_state = now+wei;
                    if(!vis[Next_state]){
                        vis[Next_state] = 1;
                        que.push(Next_state);
                    }
                    for(int k = 0; k < L; k++){
                        /*if(k == 1 && now == 1){
                            printf("--%d %d
    ", next[k][i],Next_state);
                        }*/
                        if(dp[k][now] == -1)continue;
                        dp[next[k][i]][Next_state] = max(dp[next[k][i]][Next_state], dp[k][now]+num[next[k][i]]);
                    }
                    wei *= (num_[i]+1);
                }
            }
            int ans = 0;
            int maxn = 1;
            for(int i = 0;i < 4; i++){
                maxn *= num_[i]+1;
            }
                for(int k = 0; k < maxn; k++){
            for(int i = 0; i < L; i++){//printf("%d %d %d
    ", i, k, dp[i][k]);
                    ans = max(ans, dp[i][k]);
                }
            }return ans;
        }
    };
    char buf[45];
    Tire ac;
    int main(){
        //freopen("in.cpp","r", stdin);
        mp['A'] = 0;
        mp['T'] = 1;
        mp['G'] = 2;
        mp['C'] = 3;
        int n;
        int Case = 1;
        while(scanf("%d", &n), n != 0){
            memset(num_, 0, sizeof(num_));
            ac.init();
            for(int i = 0; i < n; i++){
                scanf("%s", buf);
                ac.insert(buf, i);
            }
            scanf("%s", buf);
            memset(num, 0, sizeof(num));
            for(int i = 0; buf[i]; i++){
                num_[mp[buf[i]]] ++;
            }
            ac.build();
            printf("Case %d: %d
    ", Case ++, ac.solve());
        }
    }
    /*
    abcdefg
    bcdefg
    cdef
    de
    e
    ssaabcdefg
    
    
    */
    View Code

    3.poj2778

    题意,给出一些串,问m个字符组成的串不包含这些串的有多少种情况。

    自动机加矩阵快速幂。

    矩阵相乘就是第i行第j列的数就是前一个矩阵的第i行,与后一矩阵的第j列,要保证前一个矩阵的列数等于后一个矩阵的行数。

    构造的时候,只要把那些通向结点或通向的点的fild指向结点的节点去掉,其他正常

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    #include<map>
    using namespace std;
    const int maxa = 105;
    const int cha = 4;
    #define LL long long
    int n, m, k;
    map<char, int> mp;
    const int mod = 100000;
    struct Matrix{
        int a[maxa][maxa];
        Matrix(){
            memset(a, 0, sizeof(a));
        }
        Matrix operator *(const Matrix &b)const
        {
            Matrix ret;
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    for(int k=0;k<n;k++)
                    {
                        int tmp=(long long)a[i][k]*b.a[k][j]%mod;
                        ret.a[i][j]=(ret.a[i][j]+tmp)%mod;
                    }
            return ret;
        }/*
        Matrix operator *(const Matrix &b) const{
            Matrix tmp;
            for(int i =0 ;i < n; i++){;
                for(int j = 0; j < n; j++){
                    for(int k = 0;k  <n; k++){
                        LL lo = (LL) (tmp.a[i][j]) + (LL)(a[i][k]) *b.a[k][j];
                        lo %= mod;
                        tmp.a[i][j] = lo;
                    }
                }
            }
            return tmp;
        }*/
    };
    struct Tire{
        int next[maxa][cha], fail[maxa], end[maxa];
        int root, L;
        int newnode(){
            for(int i = 0; i < cha; i++){
                next[L][i] = -1;
            }
            end[L++] = 0;
            return L-1;
        }
        void init(){
            L = 0;
            root = newnode();
        }
        void insert(char buf[]){
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++){
                int x = mp[buf[i]];
                if(next[now][x] == -1)
                    next[now][x] = newnode();
                now = next[now][x];
                //printf("%d ", now);
            }//puts("");
            end[now] ++;
        }
        void build(){
            queue<int>Q;
            fail[root] = root;
            for(int i = 0; i < cha; i++){
                if(next[root][i] == -1)
                    next[root][i] = root;
                else{
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while(!Q.empty()){
                int now = Q.front();
                if(end[fail[now]]){
                    end[now] = 1;
                }
                Q.pop();
               // end[now] |= end[fail[now]];
                for(int i = 0; i < cha; i++){
                    if(next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else{
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                       // printf("**%d %d
    ",next[now][i],next[fail[now]][i]);
                    }
                }
            }
        }
        Matrix make_Maxtrix(){
            Matrix tmp;
            for(int i = 0; i < L; i++){
                for(int k = 0; k < cha; k++){
                    if(!end[next[i][k]]){
                        tmp.a[i][next[i][k]] ++;
                    }
                }
            }
            return tmp;
        }
    };
    Matrix pow(Matrix a,int m)
    {
        Matrix ret;// = Matrix(a.n);
        for(int i = 0; i < n; i++)
            ret.a[i][i]=1;
        Matrix tmp=a;
        while(m)
        {
            if(m&1)ret=ret*tmp;
            tmp=tmp*tmp;
            m>>=1;
        }
        return ret;
    }
    char buf[1000005];
    Tire ac;
    int main(){
    
    mp['A'] = 0;
    mp['T'] = 1;
    mp['G'] = 2;
    mp['C'] = 3;
        int N, M;
        while(scanf("%d%d", &N, &M)!=EOF){
            ac.init();
            while(N--){
                scanf("%s", buf);
                ac.insert(buf);
            }
            ac.build();
            n =  ac.L;
            Matrix a = ac.make_Maxtrix();
            Matrix b = pow(a, M);;
            int ans =0 ;
            for(int i = 0; i < n ;i++){
                ans += b.a[0][i];
                ans %= mod;
            }printf("%d
    ", ans);
        }
    }
    /*
    abcdefg
    bcdefg
    cdef
    de
    e
    ssaabcdefg
    
    
    */
    View Code

    4.ZOJ 3494 BCD Code(AC自动机+数位DP)

    题目:给出一些模式串,给出一个范围[A,B],求出区间内有多少个数,写成BCD之后,不包含模式串

    数位dp加ac自动机

    #include<string.h>
    #include<queue>
    #include<stdio.h>
    #include<iostream>
    using namespace std;
    const long long maxa = 2005;
    const long long cha = 2;
    const long long mod = 1000000009;
    struct Tire{
        long long next[maxa][cha], fail[maxa], end[maxa];
        long long root, L;
        long long newnode(){
            for(long long i = 0; i < cha; i++){
                next[L][i] = -1;
            }
            end[L++] = 0;
            return L-1;
        }
        void init(){
            L = 0;
            root = newnode();
        }
        void insert(char buf[]){
            long long len = strlen(buf);
            long long now = root;
            for(long long i = 0; i < len; i++){
                long long x = buf[i] - '0';
                if(next[now][x] == -1){
                    next[now][x] = newnode();
                }
                now = next[now][x];
            }end[now] = 1;
        }
        void build(){
            queue<int> Q;
            fail[root] = root;
            for(long long i = 0;i < cha; i++){
                if(next[root][i] == -1){
                    next[root][i] = root;
                }else{
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while(!Q.empty()){
                long long now = Q.front();Q.pop();
                if(end[fail[now]])end[now] = 1;
                for(long long i = 0; i < cha; i++){
                    if(next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else{
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                    }
                }
            }
        }
    }ac;
    /*
    struct Trie
    {
        int next[2010][2],fail[2010];
        bool end[2010];
        int root,L;
        int newnode()
        {
            for(int i = 0;i < 2;i++)
                next[L][i] = -1;
            end[L++] = false;
            return L-1;
        }
        void init()
        {
            L = 0;
            root = newnode();
        }
        void insert(char buf[])
        {
            int len = strlen(buf);
            int now = root;
            for(int i = 0;i < len ;i++)
            {
                if(next[now][buf[i]-'0'] == -1)
                    next[now][buf[i]-'0'] = newnode();
                now = next[now][buf[i]-'0'];
            }
            end[now] = true;
        }
        void build()
        {
            queue<int>Q;
            fail[root] = root;
            for(int i = 0;i < 2;i++)
                if(next[root][i] == -1)
                    next[root][i] = root;
                else
                {
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            while(!Q.empty())
            {
                int now = Q.front();
                Q.pop();
                if(end[fail[now]])end[now] = true;
                for(int i = 0;i < 2;i++)
                    if(next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else
                    {
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                    }
            }
        }
    };
    Trie ac;
    */
    //位数,节点,是否含有,是否有前导零
    long long dp[205][maxa][2][2];
    long long Next[maxa][10][2];
    void NEXT(long long now, long long kk){
        long long ok = 0;
        long long ii = now;
        for(long long i= 3; i >= 0; i--){
            ii = ac.next[ii][((1<<i)&kk)?1:0];
            if(ac.end[ii]) ok = 1;
        }
        Next[now][kk][0] = ii;
        Next[now][kk][1] = ok;
    }
    
    long long init(){
        memset(dp, -1, sizeof(dp));
        for(long long i = 0;i < ac.L; i++){
            for(long long k = 0;k < 10; k ++){
                NEXT(i, k);
            }
        }
    }
    long long num[maxa];
    long long dfs(long long pos, bool limit, bool yes, long long node, bool isZero){
        if(pos == 0){
            return yes^1;
        }
        if(!limit && isZero == 0 && dp[pos][node][yes][isZero]!=-1)
            return dp[pos][node][yes][isZero];
        long long nn = limit? num[pos]:9;
        long long res = 0;
        for(long long i = 0; i <= nn; i++){
            if(isZero&& i == 0)
                res += dfs(pos-1, limit&&i==nn, yes, node, isZero);
            else
                res += dfs(pos-1, limit &&(i == nn), Next[node][i][1]|yes, Next[node][i][0], 0);
            res %= mod;
        }
        if(!limit){
            dp[pos][node][yes][isZero] = res;
        }
        return res;
    }
    long long ans(char *a){
        long long l = strlen(a);
        for(long long i = 0; i < l ; i++){
            num[l-i] = a[i]-'0';
        }
        return dfs(l, 1, 0, 0, 1);
    }
    void a_1(char *a){
        int l = strlen(a);
        for(int i = l-1; i>= 0; i--){
            if(a[i] == '0'){
                a[i] = '9';
            }else{
                a[i] --;break;
            }
        }
    }
    char buf[maxa], buf1[maxa];
    int main(){
        long long t;
        cin>>t;
        while(t--){
            ac.init();
            long long n;
            cin>>n;
            while(n--){
                scanf("%s", buf);
                ac.insert(buf);
            }//printf("*");
            ac.build();
            init();
            scanf("%s%s", buf, buf1);
            a_1(buf);
            cout<<(mod+ans(buf1)- ans(buf))%mod<<endl;
            //printf("%d
    ", (mod+ans(buf1)- ans(buf))%mod);
        }
    }
    /*
    999992719
    4
    1
    0
    1 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    0
    1 10000000000000000000000000000
    3
    00
    0101011
    0100000
    1 10000000000000000000000000000
    5
    01010101
    010001000010
    010100000000100
    01010011111111111
    0101010100001111111
    1 10000000000000000000000000000000000000000000000000000000000000000000000000000000000
    805306365
    426375876
    */
    View Code

     5.LightOJ 1427

    题目大意:给一个长度小于10^6的字符串以及小于500个长度小于500的字符串,问每个字符串在大字符串中出现的次数。

    基础ac自动机问题,对模板做一些小修改就可以了。需要注意的是字符串有可能重复

    这是比较裸的思路,他的时间主要取决于主串的长度

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxa = 500000;
    const int cha = 26;
    int n, m, k;
    int ans[505];
    struct Tire{
        int next[maxa][cha], fail[maxa], end[maxa];
        int root, L;
        int newnode(){
            for(int i = 0; i < cha; i++){
                next[L][i] = -1;
            }
            end[L++] = 0;
            return L-1;
        }
        void init(){
            L = 0;
            root = newnode();
        }
        void insert(char buf[], int ii){
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++){
                if(next[now][buf[i] - 'a'] == -1)
                    next[now][buf[i]-'a'] = newnode();
                now = next[now][buf[i]-'a'];
                //printf("%d ", now);
            }//puts("");
            ans[ii] = now;
        }
        void build(){
            queue<int>Q;
            fail[root] = root;
            for(int i = 0; i < cha; i++){
                if(next[root][i] == -1)
                    next[root][i] = root;
                else{
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while(!Q.empty()){
                int now = Q.front();
                Q.pop();
               // end[now] |= end[fail[now]];
                for(int i = 0; i < cha; i++){
                    if(next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else{
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                       // printf("**%d %d
    ",next[now][i],next[fail[now]][i]);
                    }
                }
            }
        }
        void solve(char *s){
            //memset(ans, 0, sizeof(ans));
            int k = 0;
            for(int i = 0; s[i]; i++){
                int t = s[i] - 'a';
                k = next[k][t];
                int j = k;
                while(j){
                    end[j]++;
                    j = fail[j];
                }//puts("");
            }
            return ;
        }
    };
    char buf[1000005], buf1[1000005];
    Tire ac;
    int main(){
        int t, n;
        scanf("%d", &t);
        for(int cas = 1; cas <= t; cas++){
            scanf("%d", &n);
            ac.init();
            //memset(ac.end, 0, sizeof(ac.end));
            scanf("%s", buf1);
            for(int i = 0; i < n; i++){
                scanf("%s", buf);
                ac.insert(buf, i+1);
            }
            ac.build();
            ac.solve(buf1);
            printf("Case %d:
    ", cas);
            for(int i = 1; i <= n; i++){
                printf("%d
    ", ac.end[ans[i]]);
            }
        }
    }
    /*
    abcdefg
    bcdefg
    cdef
    de
    e
    ssaabcdefg
    
    
    */
    View Code

    这是改进过的,时间取决于树的规模,只考虑solve的过场的话时间至少优化掉四倍,从最终跑的时间来看也是这样的。

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxa = 500000;
    const int cha = 26;
    int n, m, k;
    int ans[505];
    struct Tire{
        int next[maxa][cha], fail[maxa], end[maxa];
        int qq[maxa];
        int pos[maxa], tt;
        int root, L;
        int newnode(){
            for(int i = 0; i < cha; i++){
                next[L][i] = -1;
            }
            end[L++] = 0;
            return L-1;
        }
        void init(){
            tt = 0;
            L = 0;
            root = newnode();
        }
        void insert(char buf[], int ii){
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++){
                if(next[now][buf[i] - 'a'] == -1)
                    next[now][buf[i]-'a'] = newnode();
                now = next[now][buf[i]-'a'];
                //printf("%d ", now);
            }//puts("");
            pos[ii] = now;
        }
        void build(){
            queue<int>Q;
            fail[root] = root;
            for(int i = 0; i < cha; i++){
                if(next[root][i] == -1)
                    next[root][i] = root;
                else{
                    qq[tt++] = next[root][i];
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while(!Q.empty()){
                int now = Q.front();
                Q.pop();
               // end[now] |= end[fail[now]];
                for(int i = 0; i < cha; i++){
                    if(next[now][i] == -1)
                        next[now][i] = next[fail[now]][i];
                    else{
                        qq[tt++] = next[now][i];
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                       // printf("**%d %d
    ",next[now][i],next[fail[now]][i]);
                    }
                }
            }
        }
        void solve(char *s, int n){
            memset(ans, 0, sizeof(ans));
            int k = 0;
            for(int i = 0; s[i]; i++){
                int t = s[i] - 'a';
                k = next[k][t];
                end[k] ++;
            }
            for(int i = tt-1; i >= 0; i--){
                int j = qq[i];
                    end[fail[j]] += end[j];
            }
            /*printf("*");
            for(int i = 0; i < L; i++){
                printf("%d ", end[i]);
            }puts("");*/
            for(int i = 1; i <= n; i++){
                printf("%d
    ", end[pos[i]]);
            }
            return ;
        }
    };
    char buf[1000005], buf1[1000005];
    Tire ac;
    int main(){
        int t, n;
        scanf("%d", &t);
        for(int cas = 1; cas <= t; cas++){
            scanf("%d", &n);
            ac.init();
            //memset(ac.end, 0, sizeof(ac.end));
            scanf("%s", buf1);
            for(int i = 0; i < n; i++){
                scanf("%s", buf);
                ac.insert(buf, i+1);
            }
            ac.build();
            printf("Case %d:
    ", cas);
            ac.solve(buf1, n);
        }
    }
    /*
    abcdefg
    bcdefg
    cdef
    de
    e
    ssaabcdefg
    
    
    */
    View Code

    6.hdu2243

    自动机加矩阵快速幂,和poj2778一样的解法,先求不能组成的在用所有能组成的情况减去,注意的是幂数在int以内,不知道为什么我按long long 输入然后加1就T掉了

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxa = 50;
    const int cha = 26;
    int L;
    struct Matrix{
        unsigned long long a[maxa][maxa];
        Matrix(){
            memset(a, 0, sizeof(a));
        }
        Matrix operator *(const Matrix &b)const{
            Matrix ret;
            for(int i = 0;i < L; i++){
                for(int j = 0; j < L; j++){
                    for(int k = 0; k < L; k++){
                        ret.a[i][j] = (ret.a[i][j] + a[i][k] * b.a[k][j]);
                    }
                }
            }
            return ret;
        }
    };
    Matrix pow(Matrix a, long long m){
        Matrix ret;
        for(int i = 0;i < L; i++){
            ret.a[i][i] = 1;
        }
        Matrix tmp = a;
        while(m){
            if(m & 1)
                ret = ret * tmp;
            tmp = tmp * tmp;
            m >>= 1;
        }
        return ret;
    }
    struct tire{
        int next[maxa][cha], fail[maxa], end[maxa];
        int root;
        int newnode(){
            for(int i = 0; i < cha; i++){
                next[L][i] = -1;
            }
            end[L ++] = 0;
            return L - 1;
        }
        void init(){
            L = 0;
            root = newnode();
        }
        int insert(char buf[]){
            int len = strlen(buf);
            int now = root;
            for(int i = 0; i < len; i++){
                int x = buf[i] - 'a';
                if(next[now][x] == -1){
                    next[now][x] = newnode();
                }
                now = next[now][x];
            }
            end[now] = 1;
            return now;
        }
        void build(){
            queue<int>Q;
            fail[root] = root;
            for(int i =0 ; i < cha ; i++){
                if(next[root][i] == -1){
                    next[root][i] = root;
                }
                else{
                    fail[next[root][i]] = root;
                    Q.push(next[root][i]);
                }
            }
            while(!Q.empty()){
                int now = Q.front();
                if(end[fail[now]]){
                    end[now] = 1;
                }
                Q.pop();
                for(int i =0 ;i < cha; i++){
                    if(next[now][i] == -1){
                        next[now][i] = next[fail[now]][i];
                    }
                    else{
                        fail[next[now][i]] = next[fail[now]][i];
                        Q.push(next[now][i]);
                    }
                }
            }
        }
        void make(int m){
            Matrix aa;
            for(int i =0; i < L;i ++){
                if(end[i] == 0)
                    for(int k = 0;k  < cha; k++){
                        int nxt = next[i][k];
                        if(end[nxt] == 0)
                            aa.a[nxt][i] ++;
                    }
            }
            for(int i = 0;i < L; i++){
                if(end[i] == 0)
                aa.a[L][i] = 1;
            }
            aa.a[L][L] = 1;
            /*for(int i = 0;i <= L; i++){
                for(int k = 0; k <= L; k++){
                    cout<<aa.a[i][k]<< " ";
                }
                cout<<endl;
            }*/
            aa.a[L][0] = 1;
            L ++;
            aa = aa*pow(aa, m);
            int LL = L;
            Matrix b;
            b.a[0][0] = 26;
            b.a[0][1] = 0;
            b.a[1][0] = 1;
            b.a[1][1] = 1;
            L = 2;
            b = b*pow(b, m);
            //cout<<b.a[1][0]<<" "<<aa.a[LL - 1][0]<<endl;;
            cout<<b.a[1][0] - aa.a[LL-1][0]<<endl;;
        }
    }ac;
    char buf[100];
    int main(){
        int n;
        int m;
        while(scanf("%d%d", &n, &m)!=EOF){
            ac.init();
            for(int i =0 ;i  < n; i++){
                scanf("%s", buf);
                ac.insert(buf);
            }
            ac.build();
            ac.make(m);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    switch case 变量初始化问题
    GDB 调试 ---转 比较全的东东
    mount不是很熟悉 转载文章了解下 转自http://forum.ubuntu.org.cn/viewtopic.php?f=120&t=257333
    转 strace
    Mysql 漏洞利用(越权读取文件,实战怎么从低权限拿到root密码)[转]
    echo,die(),print(),print_r(),var_dump()的区别
    iis7.5加fck解析漏洞后台拿shell
    Php发送post请求方法
    分享PHP小马一枚,完美绕过安全狗检测。
    性能测试-Gatling(一)
  • 原文地址:https://www.cnblogs.com/icodefive/p/4451679.html
Copyright © 2011-2022 走看看