字符串

0、目录

ac自动机、后缀数组、Trie树、kmp、回文串算法、后缀自动机、字符串哈希

1、ac自动机

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int maxn=1000+10;
const int maxm=50+10;
char str[maxn][maxm],s[2000000+10];
int N,num[maxn];

struct AC{
	#define sigma_size 26
	#define maxnode 50000+10
	int ch[maxnode][sigma_size];
	int val[maxnode];
	int sz;
	void init(){ sz=1; memset(ch[0],0,sizeof(ch[0])); }
	int idx(char c){ return c-'A'; }

	void insert(char *s,int v){
		int u=0,n=strlen(s);
		for(int i=0;i<n;i++){
			int c=idx(s[i]);
			if(!ch[u][c]){
				memset(ch[sz],0,sizeof(ch[sz]));
				val[sz]=0;
				ch[u][c]=sz++;
			}
			u=ch[u][c];
		}
		val[u]=v;
	}

	int f[maxnode],last[maxnode];
	int getFail(){
		queue<int> q;
		f[0]=0;
		for(int c=0;c<sigma_size;c++){
			int u=ch[0][c];
			if(u){ f[u]=0; q.push(u); last[u]=0; }
		}
		while(!q.empty()){
			int r=q.front(); q.pop();
			for(int c=0;c<sigma_size;c++){
				int u=ch[r][c];
				if(!u) continue;
				q.push(u);
				int v=f[r];
				while(v&&!ch[v][c]) v=f[v];
				f[u]=ch[v][c];
				last[u]=val[f[u]]?f[u]:last[f[u]];
			}
		}
	}
	void print(int j){
		while(j){
			num[val[j]]++;
			j=last[j];
		}
	}
	void find(char *T){
		int n=strlen(T);
		int j=0;
		for(int i=0;i<n;i++){
			int c=idx(T[i]);
			if(c<0||c>=26){ j=0; continue; };
			while(j&&!ch[j][c]) j=f[j];
			j=ch[j][c];
			if(val[j]) print(j);
			else if(last[j]) print(last[j]);
		}
	}

}ac;

void init(){
	memset(num,0,sizeof(num));
	ac.init();
}

int main(){
	while(cin>>N){
		init();
		for(int i=1;i<=N;i++){
			scanf("%s",str[i]);
			ac.insert(str[i],i);
		}
		ac.getFail();
		scanf("%s",s);
		ac.find(s);
		for(int i=1;i<=N;i++){
			if(num[i]){
				printf("%s: %d\n",str[i],num[i]);
			}
		}
	}
	return 0;
}

2、后缀数组

struct SuffixArray{
    char s[maxn];
    int sa[maxn],t[maxn],t2[maxn],c[maxn];
    int n,m;
    void init(int n,int m){
        this->n=n;
        this->m=m;
    }
    void build_sa(){
        int i,*x=t,*y=t2;
        for(i=0;i<m;i++) c[i]=0;
        for(i=0;i<n;i++) c[x[i]=s[i]]++;
        for(i=1;i<m;i++) c[i]+=c[i-1];
        for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
        for(int k=1;k<=n;k<<=1){
            int p=0;
            for(i=n-k;i<n;i++) y[p++]=i;
            for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
//            for(i=0;i<n;i++) y[p++]=(sa[i]-k+n)%n;
            
            for(i=0;i<m;i++) c[i]=0;
            for(i=0;i<n;i++) c[x[y[i]]]++;
            for(i=1;i<m;i++) c[i]+=c[i-1];
            for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
            
            swap(x,y);
            p=1; x[sa[0]]=0;
            for(i=1;i<n;i++){
                x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
            }
            if(p>=n) break;
            m=p;
        }
    }
    int rank[maxn],height[maxn];
    void getHeight(){
        int i,j,k=0;
        for(i=0;i<n;i++) rank[sa[i]]=i;
        for(i=0;i<n;i++){
            if(k) k--;
            if(rank[i]-1<0) continue; 
            int j=sa[rank[i]-1];
            while(s[i+k]==s[j+k]) k++;
            height[rank[i]]=k;
        }
    }
    void solve(){
    	build_sa();
    	getHeight();
	}
}mysa;

char str[maxn];
int main() {
    scanf("%s",&str);
    int n=strlen(str);
    mysa.init(n+1,256);//末尾要加一个特别小的符号!,这里直接用'\0'了
    strcpy(mysa.s,str);
    mysa.solve();
    return 0;
}
posted @ 2016-07-29 00:21  fenicnn  阅读(143)  评论(0编辑  收藏  举报