1 solutions

  • 0
    @ 2024-1-1 19:31:15

    难度: 紫(虚高)

    算法: AC 自动机,或其它字符串算法

    挺简单的。

    先把所有字符串插入 AC 自动机。

    然后和二次加强版差不多,把每个串当作文本串放进去匹配一遍最后再加起来就好了。

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    char s[210][1000100];
    int tr[1000100][26],fa[1000100],in[1000100],en[1000100],cnt[1000100],c;
    queue<int> q;
    void ins(int x){
    	int u=0;
    	int m=strlen(s[x]);
    	for(int i=0;i<m;i++){
    		if(tr[u][s[x][i]-'a']==0){
    			tr[u][s[x][i]-'a']=++c;
    		}
    		u=tr[u][s[x][i]-'a'];
    	}
    	en[x]=u;
    }
    void build(){
    	for(int i=0;i<26;i++){
    		if(tr[0][i]) q.push(tr[0][i]);
    	}
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		for(int i=0;i<26;i++){
    			if(tr[u][i]){
    				fa[tr[u][i]]=tr[fa[u]][i];
    				q.push(tr[u][i]);
    			}
    			else tr[u][i]=tr[fa[u]][i];
    		}
    	}
    }
    void que(int x){
    	int m=strlen(s[x]);
    	int u=0;
    	for(int i=0;i<m;i++){
    		u=tr[u][s[x][i]-'a'];
    		cnt[u]++;
    	}
    }
    void tpo(){
    	for(int i=1;i<=c;i++) in[fa[i]]++;
    	for(int i=1;i<=c;i++){
    		if(in[i]==0) q.push(i);
    	}
    	while(!q.empty()){
    		int u=q.front();
    		q.pop();
    		int v=fa[u];
    		in[v]--;
    		cnt[v]+=cnt[u];
    		if(in[v]==0) q.push(v);
    	}
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%s",s[i]);
    		ins(i);
    	}
    	build();
    	for(int i=1;i<=n;i++){
    		que(i);
    	}
    	tpo();
    	for(int i=1;i<=n;i++){
    		printf("%d\n",cnt[en[i]]);
    	}
    }
    
    • 1

    Information

    ID
    62
    Time
    1000ms
    Memory
    512MiB
    Difficulty
    10
    Tags
    # Submissions
    3
    Accepted
    3
    Uploaded By