zoukankan      html  css  js  c++  java
  • (17/34)AC自动机/后缀数组/后缀自动机(施工中)

    快补题别再摸鱼了(17/34)

    1.AC自动机


    #define maxnode 1000010
    #define maxsize 26
    struct ahocT{
        int ch[maxnode][maxsize];
        int e[maxnode],fail[maxnode];
        int sz;
        void init(){
            sz=1;memset(ch[0],0,sizeof(ch[0]));memset(e,0,sizeof(e));return;
        }
        int idx(char c) {return c-'a';}
        void insert(char *x){
            int u=0,len=strlen(x);
            FOR(i,0,len){
                int c=idx(x[i]);
                if(!ch[u][c]){
                    memset(ch[sz],0,sizeof(ch[sz]));
                    ch[u][c]=sz++;  
                }
                u=ch[u][c];
            }
            e[u]++;
            return;
        }
        void build(){
            int u;
            queue<int> q;
            memset(fail,0,sizeof(fail));
            FOR(i,0,26)
            if(ch[0][i]) q.push(ch[0][i]);
            while(!q.empty()){
                u=q.front();q.pop();
                FOR(i,0,26){
                    if(ch[u][i]) {
                        fail[ch[u][i]]=ch[fail[u]][i];
                        q.push(ch[u][i]);
                    }
                    else ch[u][i]=ch[fail[u]][i];
                }
            }
            return;
        }
        int query(char *x){
            int ans=0,c=0,len=strlen(x);
            FOR(i,0,len){
                c=ch[c][idx(x[i])];
                for(int j=c;j&&~e[j];j=fail[j]) ans+=e[j],e[j]=-1;
            }
            return ans;
        }
    }
    非拓扑序后缀链接ac自动机

    模板写法及变式(待更新)


    ac自动机的主要考察方向:DP 矩阵转移 图论


    HDU 2222

    多模式串匹配 模板题

    //#define LOCAL
    #include <cstring>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <functional>
    #include <utility>
    #include <bitset>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <cstdio>
    using namespace std;
    #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
    // X_INIT=0  mem_Macro
    #define INF 0x3f3f3f3f
    #define MOD 1000000007
    #define FOR(i,j,k) for(int i=j;i<k;i+=1)
    #define FORD(i,j,k) for(int i=j;i>k;i-=1)
    #define uLL unsigned long long
    #define LL long long
    #define SZ(x) int(x.size())
    #define pb push_back
    #define maxnode 1000010
    #define maxsize 26
    int n;
    char x[1000050];
        int ch[maxnode][maxsize];
        int e[maxnode],fail[maxnode];
        int sz;
        void init(){
            sz=1;/*memset(ch[0],0,sizeof(ch[0]));memset(e,0,sizeof(e));*/return;
        }
        int idx(char c) {return c-'a';}
        void insert(char *x){
            int u=0,len=strlen(x);
            FOR(i,0,len){
                int c=idx(x[i]);
                if(!ch[u][c]){
                    /*memset(ch[sz],0,sizeof(ch[sz]));*/
                    ch[u][c]=sz++;  
                }
                u=ch[u][c];
            }
            e[u]++;
            return;
        }
        void build(){
            int u;
            queue<int> q;
            //memset(fail,0,sizeof(fail));
            FOR(i,0,26)
            if(ch[0][i]) q.push(ch[0][i]);
            while(!q.empty()){
                u=q.front();q.pop();
                FOR(i,0,26){
                    if(ch[u][i]) {
                        fail[ch[u][i]]=ch[fail[u]][i];
                        q.push(ch[u][i]);
                    }
                    else ch[u][i]=ch[fail[u]][i];
                }
            }
            return;
        }
        int query(char *x){
            int ans=0,c=0,len=strlen(x);
            FOR(i,0,len){
                c=ch[c][idx(x[i])];
                for(int j=c;j&&~e[j];j=fail[j]) ans+=e[j],e[j]=-1;
            }
            return ans;
        }
    int main(){
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    //ahocT tr;
    int t;
    scanf("%d",&t);
    FOR(i,0,t){
    init();
    sz=1;
    scanf("%d",&n);
    FOR(i,0,n){
        scanf("%s",x);
        insert(x);
    }
    build();
    scanf("%s",x);
    printf("%d
    ",query(x));
    }
    //system("pause");
    #ifdef LOCAL
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
    }
    ac代码

    HDU 2896

    多模式串匹配统计,多模板串set处理

    //#define LOCAL
    #include <cstring>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <functional>
    #include <utility>
    #include <bitset>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <cstdio>
    using namespace std;
    #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
    // X_INIT=0  mem_Macro
    #define INF 0x3f3f3f3f
    #define MOD 1000000007
    #define FOR(i,j,k) for(int i=j;i<k;i+=1)
    #define FORD(i,j,k) for(int i=j;i>k;i-=1)
    #define uLL unsigned long long
    #define LL long long
    #define SZ(x) int(x.size())
    #define pb push_back
    #define maxnode 100010
    #define maxsize 130
    int l,n;
    char x[10010];
    struct ahocT{
        int ch[maxnode][maxsize];
        int e[maxnode],fail[maxnode],vis[maxnode];
        int sz;
        void init(){
            sz=1;memset(ch[0],0,sizeof(ch[0]));memset(e,0,sizeof(e));return;
        }
        int idx(char c) {return (int)c;}
        void insert(char *x,int num){
            int u=0,len=strlen(x);
            FOR(i,0,len){
                int c=idx(x[i]);
                if(!ch[u][c]){
                    memset(ch[sz],0,sizeof(ch[sz]));
                    ch[u][c]=sz++;  
                }
                u=ch[u][c];
            }
            e[u]=num;
            return;
        }
        void build(){
            int u;
            queue<int> q;
            memset(fail,0,sizeof(fail));
            FOR(i,0,129)
            if(ch[0][i]) q.push(ch[0][i]);
            while(!q.empty()){
                u=q.front();q.pop();
                FOR(i,0,129){
                    if(ch[u][i]) {
                        fail[ch[u][i]]=ch[fail[u]][i];
                        q.push(ch[u][i]);
                    }
                    else ch[u][i]=ch[fail[u]][i];
                }
            }
            return;
        }
        int query(char *x,int ii){
            int ans=0,c=0,len=strlen(x);
            memset(vis,0,sizeof(vis));
            FOR(i,0,len){
                c=ch[c][idx(x[i])];
                for(int j=c;j&&~e[j];j=fail[j]) vis[e[j]]++,ans+=e[j];
            }
            if(ans) {printf("web %d:",ii);
            FOR(j,1,sz)
            if(e[j]) if(vis[e[j]]) printf(" %d",e[j]);
            printf("
    ");return 1;} else return 0;
        }
    };
    ahocT xx;
    int main(){
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    scanf("%d",&n);
    xx.init();
    FOR(i,1,n+1){
    scanf("%s",x);
    xx.insert(x,i);
    }
    xx.build();
    scanf("%d",&n);
    int l=0;
    FOR(i,1,n+1){
        scanf("%s",x);
        l+=xx.query(x,i);
    
    }
    printf("total: %d
    ",l);
    //system("pause");
    #ifdef LOCAL
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
    }
    ac代码

    HDU 3065

    多模式串匹配统计次数

    为防止多个模式串重复,一般分配map映射

    //#define LOCAL
    #include <cstring>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <functional>
    #include <utility>
    #include <bitset>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <cstdio>
    using namespace std;
    #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
    // X_INIT=0  mem_Macro
    #define INF 0x3f3f3f3f
    #define MOD 1000000007
    #define FOR(i,j,k) for(int i=j;i<k;i+=1)
    #define FORD(i,j,k) for(int i=j;i>k;i-=1)
    #define uLL unsigned long long
    #define LL long long
    #define SZ(x) int(x.size())
    #define pb push_back
    #define maxnode 100010
    #define maxsize 130
    int l,n;
    char lx[1010][60];
    char xxx[2000010];
    struct ahocT{
        int ch[maxnode][maxsize];
        int e[maxnode],fail[maxnode],vis[maxnode];
        int idxx[maxnode];
        int sz;
        void init(){
            sz=1;memset(ch[0],0,sizeof(ch[0]));memset(e,0,sizeof(e));return;
        }
        int idx(char c) {return (int)c;}
        void insert(char *x,int num){
            int u=0,len=strlen(x);
            FOR(i,0,len){
                int c=idx(x[i]);
                if(!ch[u][c]){
                    memset(ch[sz],0,sizeof(ch[sz]));
                    ch[u][c]=sz++;  
                }
                u=ch[u][c];
            }
            e[u]=num;idxx[num]=u;
            return;
        }
        void build(){
            int u;
            queue<int> q;
            memset(fail,0,sizeof(fail));
            FOR(i,0,129)
            if(ch[0][i]) q.push(ch[0][i]);
            while(!q.empty()){
                u=q.front();q.pop();
                FOR(i,0,129){
                    if(ch[u][i]) {
                        fail[ch[u][i]]=ch[fail[u]][i];
                        q.push(ch[u][i]);
                    }
                    else ch[u][i]=ch[fail[u]][i];
                }
            }
            return;
        }
        void query(char *x){
            int ans=0,c=0,len=strlen(x);
            memset(vis,0,sizeof(vis));
            FOR(i,0,len){
                c=ch[c][idx(x[i])];
                for(int j=c;j&&~e[j];j=fail[j]) vis[j]++,ans+=e[j];
            }
           //printf("web %d:",ii);
            FOR(j,1,n+1){
                if(vis[idxx[j]])
                printf("%s: %d
    ",lx[j],vis[idxx[j]]);
            }
            //if(e[j]) if(vis[e[j]]) printf(" %d",e[j]);
            //printf("
    ");return 1;} else return 0;
            return;
        }
    };
    ahocT xx;
    int main(){
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    while(scanf("%d",&n)!=EOF){
    xx.init();
    FOR(i,1,n+1){
    scanf("%s",lx[i]);
    xx.insert(lx[i],i);
    }
    xx.build();
    //scanf("%d",&n);
    //int l=0;
    //FOR(i,1,n+1){
        scanf("%s",xxx);
        xx.query(xxx);
    //cout<<xxx;
    //}
    //printf("total: %d
    ",l);
    }
    //system("pause");
    #ifdef LOCAL
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
    }
    ac代码

    ZOJ 3430

    base64转码+多模式串匹配统计

    //#define LOCAL
    #include <cstring>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <functional>
    #include <utility>
    #include <bitset>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <cstdio>
    using namespace std;
    #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
    // X_INIT=0  mem_Macro
    #define INF 0x3f3f3f3f
    #define MOD 1000000007
    #define FOR(i,j,k) for(int i=j;i<k;i+=1)
    #define FORD(i,j,k) for(int i=j;i>k;i-=1)
    #define uLL unsigned long long
    #define LL long long
    #define SZ(x) int(x.size())
    #define pb push_back
    #define maxnode 50010
    #define maxsize 256
    char x[2100];
    int xx[4000];
    int id(char c) {
        if(c >= 'A' && c <= 'Z') return c - 'A';
        else if(c >= 'a' && c <= 'z') return  c - 'a' + 26;
        else if(c >= '0' && c <= '9') return c - '0' + 52;
        else if(c == '+') return 62;
        else return 63;
    }
    struct ahocT{
        int ch[maxnode][maxsize];
        int e[maxnode],fail[maxnode];
        int vis[maxnode];
        int sz;
        void init(){
            sz=1;memset(ch[0],0,sizeof(ch[0]));memset(e,0,sizeof(e));return;
        }
        int idx(int c) {return c;}
        void insert(int *x,int len){
            int u=0;//,len=strlen(x);
            FOR(i,0,len){
                int c=idx(x[i]);
                if(!ch[u][c]){
                    memset(ch[sz],0,sizeof(ch[sz]));
                    ch[u][c]=sz++;  
                }
                u=ch[u][c];
            }
            e[u]++;
            return;
        }
        void build(){
            int u;
            queue<int> q;
            memset(fail,0,sizeof(fail));
            FOR(i,0,256)
            if(ch[0][i]) q.push(ch[0][i]);
            while(!q.empty()){
                u=q.front();q.pop();
                FOR(i,0,256){
                    if(ch[u][i]) {
                        fail[ch[u][i]]=ch[fail[u]][i];
                        q.push(ch[u][i]);
                    }
                    else ch[u][i]=ch[fail[u]][i];
                }
            }
            return;
        }
        int query(int *x,int len){
            int ans=0,c=0;//len=strlen(x);
            memset(vis,0,sizeof(vis));
            FOR(i,0,len){
                c=ch[c][idx(x[i])];
                for(int j=c;j&&~e[j];j=fail[j]) if(vis[j]==0) {ans+=e[j],vis[j]=1;}
                //{ans+=e[j],e[j]=-1;}
            }
            return ans;
        }
    } tt;
    int main(){
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    int n,m;
    while(scanf("%d",&n)!=EOF){
        tt.init();
        //cout<<"**";
        FOR(i,0,n){
            scanf("%s",x);
            int len=strlen(x);
            int cnt=0;
            while(x[len-1]=='=') len--;
            for(int j=0;j<len;j+=4){
                xx[cnt++]=(id (x[j])<<2|id(x[j+1])>>4);//6 2
                if(j+2<len) xx[cnt++]=((id(x[j+1])&0x0f)<<4)|id(x[j+2])>>2;//4 4
                if(j+3<len) xx[cnt++]=((id(x[j+2])&0x03)<<6)|id(x[j+3]);//2 6
            }
          /* FOR(j,0,cnt)
           cout<<xx[j]<<' ';
           cout<<' '<<endl;*/
            tt.insert(xx,cnt);
        }
        tt.build();
        scanf("%d",&m);
        FOR(i,0,m){
            scanf("%s",x);
            int len=strlen(x);
            int cnt=0;
             while(x[len-1]=='=') len--;
           for(int j=0;j<len;j+=4){
                xx[cnt++]=(id(x[j])<<2|id(x[j+1])>>4);//6 2
                if(j+2<len) xx[cnt++]=((id(x[j+1])&0x0f)<<4)|id(x[j+2])>>2;//4 4
                if(j+3<len) xx[cnt++]=((id(x[j+2])&0x03)<<6)|id(x[j+3]);//2 6
            }
           /*  FOR(j,0,cnt)
           cout<<xx[j]<<' ';
           cout<<' '<<endl;*/
           printf("%d
    ",tt.query(xx,cnt));
        }
        printf("
    ");
    }
    //system("pause");
    #ifdef LOCAL
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
    }
    ac代码

    POJ 2778

    求不出现模式串的定长构造串个数

    矩阵快速幂转移fail矩阵 求sigma(fail[0][i])

    //#define LOCAL
    #include <cstring>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <functional>
    #include <utility>
    #include <bitset>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <cstdio>
    using namespace std;
    #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
    // X_INIT=0  mem_Macro
    #define INF 0x3f3f3f3f
    #define MOD 1000000007
    #define FOR(i,j,k) for(int i=j;i<k;i+=1)
    #define FORD(i,j,k) for(int i=j;i>k;i-=1)
    #define uLL unsigned long long
    #define LL long long
    #define SZ(x) int(x.size())
    #define pb push_back
    #define maxnode 110
    #define maxsize 26
    char x[20];
    LL dp[101][101];
    map<char,int> id;
    struct ahocT{
        int ch[maxnode][maxsize];
        int e[maxnode],fail[maxnode];
        int sz;
        void init(){
            sz=1;memset(ch[0],0,sizeof(ch[0]));memset(e,0,sizeof(e));return;
        }
        int idx(char c) {return id[c];}
        void insert(char *x){
            int u=0,len=strlen(x);
            FOR(i,0,len){
                int c=idx(x[i]);
                if(!ch[u][c]){
                    memset(ch[sz],0,sizeof(ch[sz]));
                    ch[u][c]=++sz;  
                }
                u=ch[u][c];
            }
            e[u]++;
            return;
        }
        void build(){
            int u;
            queue<int> q;
            memset(fail,0,sizeof(fail));
            FOR(i,0,4)
            if(ch[0][i]) q.push(ch[0][i]);
            while(!q.empty()){
                u=q.front();q.pop();
                FOR(i,0,4){
                    if(ch[u][i]) {
                        fail[ch[u][i]]=ch[fail[u]][i];
                        q.push(ch[u][i]);
                        if(e[fail[ch[u][i]]]) e[ch[u][i]]=1;
                        }
                    else ch[u][i]=ch[fail[u]][i];
                }
            }
            return;
        }
        int query(char *x){
            int ans=0,c=0,len=strlen(x);
            FOR(i,0,len){
                c=ch[c][idx(x[i])];
                for(int j=c;j&&~e[j];j=fail[j]) ans+=e[j],e[j]=-1;
            }
            return ans;
        }
    }tt;
    /*()
    void(LL *a,int len,int cc){
        LL xx[len+1][len+1],tmp[len+1][len+1],ans[len+1][len+1];
        int c=cc;
        //memset(xx,0,sizeof(xx))拢禄
        FOR(i,0,len)
        FOR(j,0,len)
        xx[i][j]=a[i][j];
        while(c){
            if(c&1){
                FOR(i,0,len)
                FOR(j,0,len)
                FOR(k,0,len)
                tmp[i][j]+=ans[i][k]*a[k][j];
                FOR(i,0,len)
                FOR(j,0,len)
                ans[i][j]=tmp[i][j];
            }
             FOR(i,0,len)
             FOR(j,0,len)
             FOR(k,0,len)
             tmp[i][j]+=xx[i][k]*xx[k][j];
             FOR(i,0,len)
             FOR(j,0,len)
             xx[i][j]=tmp[i][j];
             c/=2;
        }
        int anss=0;
        FOR(i,0,len)
        anss+=ans[0][i];
        printf("%lld
    ",anss);
        return;
    }*/
    int main(){
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    id['A']=0;
    id['T']=1;
    id['G']=2;
    id['C']=3;
    int m,n;
    scanf("%d%d",&m,&n);
    FOR(i,0,m){
    scanf("%s",x);
    tt.insert(x);
    }
    tt.build();
    //cout<<tt.sz;
    int len=tt.sz+1;
    FOR(i,0,tt.sz+1){
        if(!tt.e[i])
        FOR(j,0,4)
        if(!tt.e[tt.ch[i][j]])dp[i][tt.ch[i][j]]++;
    }
    /*FOR(i,0,tt.sz+1){
        FOR(j,0,tt.sz+1)
        cout<<dp[i][j];
        cout<<endl;
    }*/
    //q_pow(dp,len,m);
    LL xx[101][101],tmp[101][101],ans[101][101];
        int c=n;
        memset(ans,0,sizeof(ans));
        FOR(i,0,len)
        FOR(j,0,len)
        xx[i][j]=dp[i][j];
        FOR(i,0,len)
        ans[i][i]=1;
        while(c){
           // cout<<c<<endl;
            if(c&1){ memset(tmp,0,sizeof(tmp));
                FOR(i,0,len)
                FOR(j,0,len)
                FOR(k,0,len)
                tmp[i][j]+=xx[i][k]*ans[k][j],tmp[i][j]%=100000;
                FOR(i,0,len)
                FOR(j,0,len)
                ans[i][j]=tmp[i][j];
            }
             memset(tmp,0,sizeof(tmp));
             FOR(i,0,len)
             FOR(j,0,len)
             FOR(k,0,len)
             tmp[i][j]+=xx[i][k]*xx[k][j],tmp[i][j]%=100000;
             FOR(i,0,len)
             FOR(j,0,len)
             xx[i][j]=tmp[i][j];
             c>>=1;
        /*         FOR(i,0,len){
        FOR(j,0,len)
        cout<<ans[i][j];
        cout<<endl;}
        
        */}
        LL anss=0;
        FOR(i,0,len)
        anss+=ans[0][i];
        printf("%lld
    ",anss%100000);
    //system("pause");
    #ifdef LOCAL
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
    }
    ac代码

    HDU 2243

    求出现模式串的不定长构造串个数

    构造矩阵A:【fail      E】和B:【26      1】

            【0    E】      【0    1】

    矩阵快速幂转移后求B左上与A右上第一行simga之差

    #include <cstring>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <functional>
    #include <utility>
    #include <bitset>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <cstdio>
    using namespace std;
    #define X_mem(x,y,z) (X_mem[x][y][z] ? X_mem[x][y][z] :X_mem[x][y][z]=mem(x,y,z))
    // X_INIT=0  mem_Macro
    #define INF 0x3f3f3f3f
    #define MOD 1000000007
    #define FOR(i,j,k) for(int i=j;i<k;i+=1)
    #define FORD(i,j,k) for(int i=j;i>k;i-=1)
    #define uLL unsigned long long
    #define LL long long
    #define SZ(x) int(x.size())
    #define pb push_back
    #define maxnode 110
    #define maxsize 26
    #define N 100
    struct Mat{
        uLL mat[N][N];
    };
    Mat operator *(Mat x,Mat y){
        Mat c;
        memset(c.mat,0,sizeof(c.mat));
        FOR(k,0,N)
        FOR(i,0,N){
        if(x.mat[i][k]<=0) continue;
            FOR(j,0,N){
                if(y.mat[k][j]<=0) continue; 
                    c.mat[i][j]+=x.mat[i][k]*y.mat[k][j];
            }
        }
        return c;
    }
    char x[20];
    uLL dp[101][101];
    map<char,int> id;
    
    struct ahocT{
        int ch[maxnode][maxsize];
        int e[maxnode],fail[maxnode];
        int sz;
        void init(){
            sz=1;memset(ch[0],0,sizeof(ch[0]));memset(e,0,sizeof(e));return;
        }
        int idx(char c) {return c-'a';}
        void insert(char *x){
            int u=0,len=strlen(x);
            FOR(i,0,len){
                int c=idx(x[i]);
                if(!ch[u][c]){
                    memset(ch[sz],0,sizeof(ch[sz]));
                    ch[u][c]=sz++;  
                }   
                u=ch[u][c];
            }
            e[u]++;
            return;
        }
        void build(){
            int u;
            queue<int> q;
            memset(fail,0,sizeof(fail));
            FOR(i,0,26)
            if(ch[0][i]) q.push(ch[0][i]);
            while(!q.empty()){
                u=q.front();q.pop();
                FOR(i,0,26){
                    if(ch[u][i]) {
                        fail[ch[u][i]]=ch[fail[u]][i];
                        q.push(ch[u][i]);
                        if(e[fail[ch[u][i]]]) e[ch[u][i]]=1;
                        }
                    else ch[u][i]=ch[fail[u]][i];
                }
            }
            return;
        }
        int query(char *x){
            int ans=0,c=0,len=strlen(x);
            FOR(i,0,len){
                c=ch[c][idx(x[i])];
                for(int j=c;j&&~e[j];j=fail[j]) ans+=e[j],e[j]=-1;
            }
            return ans;
        }
    }tt;
    Mat qpow(Mat x,int le){
        Mat res;
        memset(res.mat,0,sizeof(res.mat));
        int cc=le;
        FOR(i,0,N)
        res.mat[i][i]=1;
        while(cc){
            if(cc&1) res=res*x;
            x=x*x;
            cc>>=1;
        }
        return res;
    }
    int main(){
    int m,n;
    
    while(scanf("%d%d",&m,&n)!=EOF){
    tt.init();
    FOR(i,0,m){
    scanf("%s",x);
    tt.insert(x);
    }
    tt.build();
    Mat dp;
    memset(dp.mat,0,sizeof(dp.mat));
    FOR(i,0,tt.sz){
        if(tt.e[i]) continue;
        FOR(j,0,26)
        if(tt.e[tt.ch[i][j]]==0)dp.mat[i][tt.ch[i][j]]++;
    }
    FOR(i,tt.sz,2*tt.sz)
    dp.mat[i-tt.sz][i]=1;
    FOR(i,tt.sz,2*tt.sz)
    dp.mat[i][i]=1;/*
    FOR(i,0,tt.sz)
    cout<<tt.e[i];
    cout<<tt.sz<<endl;
    
    FOR(i,0,2*tt.sz){
        FOR(j,0,2*tt.sz)
        cout<<dp.mat[i][j]<<' ';
        cout<<endl;
    }*/dp=qpow(dp,n);
    uLL ans=0;
    FOR(i,0,2*tt.sz)
    ans+=dp.mat[0][i];
    ans--;
    //LL ans=dp.mat[0][tt.sz+1]-1;
    Mat p;
    memset(p.mat,0,sizeof(p.mat));
    p.mat[0][0]=26;p.mat[0][1]=1;p.mat[1][1]=1;
    p=qpow(p,n);
    uLL ans2=p.mat[0][0]+p.mat[0][1];
    ans2--;
    cout<<ans2-ans<<endl;
    }
    return 0;
    }
    ac代码

     POJ 1625

    求不出现模式串的定长构造串个数的高精度大数

    加上大数模板

    未写题:

     HDU 2825 

    HDU 2296

     HDU 2457

     ZOJ 3228 

    HDU 3341

     HDU 3247

     HDU 4758

     HDU 4511

    2.后缀数组


    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    
    const int N = 1000010;
    
    char s[N];
    int n, w, sa[N], rk[N << 1], oldrk[N << 1];
    // 为了防止访问 rk[i+w] 导致数组越界,开两倍数组。
    // 当然也可以在访问前判断是否越界,但直接开两倍数组方便一些。
    
    int main() {
      int i, p;
    
      scanf("%s", s + 1);
      n = strlen(s + 1);
      for (i = 1; i <= n; ++i) rk[i] = s[i];
    
      for (w = 1; w < n; w <<= 1) {
        for (i = 1; i <= n; ++i) sa[i] = i;
        sort(sa + 1, sa + n + 1, [](int x, int y) {
          return rk[x] == rk[y] ? rk[x + w] < rk[y + w] : rk[x] < rk[y];
        });  // 这里用到了 lambda
        memcpy(oldrk, rk, sizeof(rk));
        // 由于计算 rk 的时候原来的 rk 会被覆盖,要先复制一份
        for (p = 0, i = 1; i <= n; ++i) {
          if (oldrk[sa[i]] == oldrk[sa[i - 1]] &&
              oldrk[sa[i] + w] == oldrk[sa[i - 1] + w]) {
            rk[sa[i]] = p;
          } else {
            rk[sa[i]] = ++p;
          }  // 若两个子串相同,它们对应的 rk 也需要相同,所以要去重
        }
      }
    
      for (i = 1; i <= n; ++i) printf("%d ", sa[i]);
    
      return 0;
    }
    SA原版
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    
    const int N = 1000010;
    
    char s[N];
    int n, sa[N], rk[N << 1], oldrk[N << 1], id[N], cnt[N];
    
    int main() {
      int i, m, p, w;
    
      scanf("%s", s + 1);
      n = strlen(s + 1);
      m = max(n, 300);
      for (i = 1; i <= n; ++i) ++cnt[rk[i] = s[i]];
      for (i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
      for (i = n; i >= 1; --i) sa[cnt[rk[i]]--] = i;
    
      for (w = 1; w < n; w <<= 1) {
        memset(cnt, 0, sizeof(cnt));
        for (i = 1; i <= n; ++i) id[i] = sa[i];
        for (i = 1; i <= n; ++i) ++cnt[rk[id[i] + w]];
        for (i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
        for (i = n; i >= 1; --i) sa[cnt[rk[id[i] + w]]--] = id[i];
        memset(cnt, 0, sizeof(cnt));
        for (i = 1; i <= n; ++i) id[i] = sa[i];
        for (i = 1; i <= n; ++i) ++cnt[rk[id[i]]];
        for (i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
        for (i = n; i >= 1; --i) sa[cnt[rk[id[i]]]--] = id[i];
        memcpy(oldrk, rk, sizeof(rk));
        for (p = 0, i = 1; i <= n; ++i) {
          if (oldrk[sa[i]] == oldrk[sa[i - 1]] &&
              oldrk[sa[i] + w] == oldrk[sa[i - 1] + w]) {
            rk[sa[i]] = p;
          } else {
            rk[sa[i]] = ++p;
          }
        }
      }
    
      for (i = 1; i <= n; ++i) printf("%d ", sa[i]);
    
      return 0;
    }
    去掉一个log
    for (i = 1, k = 0; i <= n; ++i) {
      if (k) --k;
      while (s[i + k] == s[sa[rk[i] - 1] + k]) ++k;
      ht[rk[i]] = k;  // height太长了缩写为ht
    }
    height(未加st+rmq)

    模板写法及变式(待更新)


    询问子串[L,R]的出现次数

    处理出height数组后左右二分找到第一个lcp小于R-L+1的坐标相减

    求最长重复子串

    max(height)即可

    poj 1743

    求不可重叠最长重复子串

    二分答案(重复子串的长度)然后沿着sa做一遍分块,保证每个块中最多没有一个串的height小于所选答案,处理出此块中最大最小的下标,与枚举的答案长度做比较。

    poj 3261

    求可重叠出现k次的最长重复子串

    二分答案(重复子串的长度)然后沿着sa做一遍分块,保证每个块中最多没有一个串的height小于所选答案,处理出此块中的串数是否大于k

    spoj 694(重要)

    求真实子串个数

    len*(len-1)/2-sigma(height[i])

    最长回文子串(重要)

    S+'$'+反S跑一遍SA,然后分奇偶讨论情况

    lcp(suf【i】,suf【n-i+1】) lcp(suf【i】,suf【n】)

    poj 2406

    求连续重复子串

    枚举子串长度l,检验lcp(suf(0),suf(len))=n-len

    poj3693

    求重复次数最多的重复子串

    枚举子串长度l,检验lcp(suf(0),suf(len))=n-len,求max(n/(len))

    poj 2774

    求最长公共子串

    A+‘$’+B跑一遍sa,沿着sa求一遍不可重叠最长重复子串就ok

    poj 3415

    长度不小于k的公共子串个数

    A+‘$’+B跑一遍sa+沿着sa搞单调栈再求不可重叠最长重复子串

    未写题:

    SPOJ DISUBSTR

    SPOJ SUBST1 

    SPOJ REPEATs 

    POJ 3294 

    SPOJ PHRASEs 

    POJ 1226 

    UVA 11475 

    POJ 3581 

    POJ 3450 

    POJ 2758

  • 相关阅读:
    svn的使用
    判断某个ImageView的背景图是否是已知的背景图相等
    关于fragment点击穿透的问题
    使用fragment添加底部导航栏
    HTML基本格式
    Handler机制
    在Android studio中到入Eclipse
    关于即来即停app的功能
    Memcached 笔记与总结(8)Memcached 的普通哈希分布算法和一致性哈希分布算法命中率对比
    大数据对互联网金融的影响
  • 原文地址:https://www.cnblogs.com/mukoiaoi/p/12597822.html
Copyright © 2011-2022 走看看