(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\n",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("\n");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\n",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\n",lx[j],vis[idxx[j]]);
        }
        //if(e[j]) if(vis[e[j]]) printf(" %d",e[j]);
        //printf("\n");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\n",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\n",tt.query(xx,cnt));
    }
    printf("\n");
}
//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\n",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\n",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

posted @ 2020-03-30 12:37  MukoiAoi  阅读(202)  评论(0编辑  收藏  举报