AC自动机

二次加强版那个题
距离最大内存,就差了一个ss数组了....96分

#include<bits/stdc++.h>
#define maxn 2000001
using namespace std;
string ss[100000];
char s[maxn],T[maxn];
int n,cnt,vis[200051],ans,in[maxn],Map[maxn];
struct kkk{
    int son[26],fail,flag,ans;
    void clear(){memset(son,0,sizeof(son)),fail=flag=ans=0;}
}trie[maxn];
queue<int>q;
//int getnum(char x){
//    if(x>='A'&&x<='Z')
//        return x-'A';
//    else if(x>='a'&&x<='z')
//        return x-'a'+26;//由于这个26,对于最大值那个问题,这个位置并不适用 
//    else
//        return x-'0'+52;
//} 
void insert(char* s,int num){
    int u=1,len=strlen(s);
    for(int i=0;i<len;i++){
//        int v=getnum(s[i]);
		int v=s[i]-'a';//只有字母 
        if(!trie[u].son[v])trie[u].son[v]=++cnt;
        u=trie[u].son[v];
    }
    if(!trie[u].flag)trie[u].flag=num;
    Map[num]=trie[u].flag;
}
void getFail(){
    for(int i=0;i<26;i++)trie[0].son[i]=1;
    q.push(1);
    while(!q.empty()){
        int u=q.front();q.pop();
        int Fail=trie[u].fail;
        for(int i=0;i<26;i++){
            int v=trie[u].son[i];
            if(!v){trie[u].son[i]=trie[Fail].son[i];continue;}
            trie[v].fail=trie[Fail].son[i]; in[trie[v].fail]++;
            q.push(v);
        }
    }
}
void topu(){
    for(int i=1;i<=cnt;i++)
    if(in[i]==0)q.push(i);
    while(!q.empty()){
        int u=q.front();q.pop();vis[trie[u].flag]=trie[u].ans;
        int v=trie[u].fail;in[v]--;
        trie[v].ans+=trie[u].ans;
        if(in[v]==0)q.push(v);
    }
}
void query(char* s){
    int u=1,len=strlen(s);
    for(int i=0;i<len;i++)
    u=trie[u].son[s[i]-'a'],trie[u].ans++;
}
int main(){
while(scanf("%d",&n))
{
	for(int i=0;i<=1000000;i++)
	{
		trie[i].clear();
	}
	if(n==0)
	return 0;
	    cnt=1;
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        ss[i]=s;
        insert(s,i);
    }getFail();scanf("%s",T);
    query(T);topu();
    
    
    
/*输出实体,输出最大值*/
    vector<int> damn(vis,vis+n+1);//保存个数 (因为Map和vis有个对应关系) 
    sort(&vis[1],&vis[n+1]);//得到最大的个数 
    cout<<vis[n]<<endl;
    for(int i=1;i<=n;i++)
	{
		if(damn[Map[i]]==vis[n])//如果 
		cout<<ss[Map[i]]<<endl;
	}
 } 





//i:字符串的编号 
/*就是在个数和实体之间用Map[i]代替i了,但前提是vis和ss都不能变*/
//vis[Map[i]]  第i个字符串的个数 
//ss[Map[i]]   第i个字符串的实体 


    
/*输出每个字符串出现的次数*/
//  for(int i=1;i<=n;i++)printf("%d\n",vis[Map[i]]);






/*输出有多少个出现过*/
/*不怕重复的字符串了*/
//	int hh=0;
//	for(int i=1;i<=n;i++)
//	{
//		if(vis[Map[i]]>0)
//		hh++;
//	}
//	printf("%d",hh);
}



posted @   涤生yang  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示