hdu2222 Keywords Search [kuangbin专题-ac自动机]

ac自动机裸题,可以拿个板子走

#include <bits/stdc++.h>
#define fi first
#define se second
#define FIN freopen("in.txt","r",stdin)
#define FIO freopen("out.txt","w",stdout)
#define INF 0x3f3f3f3f
#define per(i,a,n) for(int i = a;i < n;i++)
#define rep(i,a,n) for(int i = n;i > a;i--)
#define pern(i,a,n) for(int i = a;i <= n;i++)
#define repn(i,a,n) for(int i = n;i >= a;i--)
#define fastio std::ios::sync_with_stdio(false)
#define all(a) a.begin(), a.end()
#define ll long long
#define pb push_back
#define endl "\n"
#define mp make_pair
#define pii pair<int,int>
#define sc(n) scanf("%d", &n)
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
template<typename T> inline void _max(T &a,const T b){
    
    if(a<b) a = b;}
template<typename T> inline void _min(T &a,const T b){
    
    if(a>b) a = b;}
using namespace std;
inline ll read(){
    
    
    ll a=0;int f=0;char p=getchar();
    while(!isdigit(p)){
    
    f|=p=='-';p=getchar();}
    while(isdigit(p)){
    
    a=(a<<3)+(a<<1)+(p^48);p=getchar();}
    return f?-a:a;
}
const int maxn = 10000*50;
int ch[maxn][26];//字典树
int cnt[maxn];//单词出现次数
int sz;
void init()
{
    
    
    sz = 0;
    memset(ch[0],0,sizeof(ch[0]));
    //val[0] = 0;
    cnt[0] = 0;
}
void insert(char str[],int len)//插入字符串
{
    
    
    int u = 0;
    per(i,0,len)
    {
    
    
        int v = str[i]-'a';
        if(!ch[u][v])
        {
    
    
            sz++;
            memset(ch[sz],0,sizeof(ch[sz]));
            //val[sz] = 0;
            cnt[sz] = 0;
            ch[u][v] = sz;
        }
        u = ch[u][v];
    }
    cnt[u]++;
    //cout << u << ' ';
    //在这里我们可以建立一个int-string的映射,以通过节点序号得知这个点是哪个单词的结尾
}
int fail[maxn];
void getfail()
{
    
    
    //所有模式串已插入完成
    queue<int> q;
    fail[0] = 0;
    per(i,0,26)
    {
    
    
        if(ch[0][i])
        {
    
    
            fail[ch[0][i]] = 0;
            q.push(ch[0][i]);
        }
    }
    while(!q.empty())
    {
    
    
        int now = q.front();
        q.pop();
        per(i,0,26)
        {
    
    
            if(ch[now][i])
            {
    
    
                fail[ch[now][i]] = ch[fail[now]][i];
                q.push(ch[now][i]);
            }
            else
                ch[now][i] = ch[fail[now]][i];
        }
    }
}
int query(char str[],int len)
{
    
    
    int now = 0,ans = 0;
    per(i,0,len)
    {
    
    
        now = ch[now][str[i]-'a'];
        int j = now;

        while(j && cnt[j]!=-1)
        {
    
    
            //cout << j << ' ';
            ans+=cnt[j];
            cnt[j] = -1;//防止重复计算。这里可以将j映射到string,以具体统计每个模式串出现的次数。j即节点序号,模式串与其是一一对应的关系
            j = fail[j];
        }
    }
    return ans;
}
char s[1000000+10];
int main()
{
    
    

    #ifndef ONLINE_JUDGE
        int startTime = clock();
        FIN;
    #endif
    //fastio;
	//忘记初始化是小狗
    //freopen("out.txt","w",stdout);
    //ios::sync_with_stdio(false);
    int n;

    CASET
    {
    
    
        init();
        sc(n);
        per(i,0,n)
        {
    
    
            scanf("%s",s);
        //    printf("%s\n",s);
            insert(s,strlen(s));
        }
        scanf("%s",s);
        //printf("%s",s);
        getfail();
        printf("%d\n",query(s,strlen(s)));
    }
    #ifndef ONLINE_JUDGE
        printf("\nTime = %dms\n", clock() - startTime);
    #endif
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39586345/article/details/108531997