• 字符串


    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
    ",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);//末尾要加一个特别小的符号!,这里直接用''了
        strcpy(mysa.s,str);
        mysa.solve();
        return 0;
    }
  • 相关阅读:
    roscore提示“ModuleNotFoundError: No module named 'defusedxml'”的解决。
    Linux下/home/用户名/.local文件
    vscode 使用技巧一-列编辑。
    Ubuntu下安装visual studio code
    第一阶段(七)
    第一阶段(六)
    Python爬取imdb电影数据并存储到mysql数据库
    第一阶段(五)
    第一阶段(四)
    第一阶段(三)
  • 原文地址:https://www.cnblogs.com/fenice/p/5716833.html
Copyright © 2020-2023  润新知