顺手水了一道trie,原来都是直接写静态的,这次用后缀自动机的存储方式写了一下,写成这种“伪动态”的存储方式即比静态的省空间,而且也没写动态的那么多麻烦。

题目的话,插入的时候沿路径吧每个节点的权值加一,统计的时候直接输出当前前缀走到底时的节点上的权值即可。走空就是0了。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <cstdio>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long ll;
const int S=26;
const int maxn=1000000+10;
struct node
{
    node* go[S];
    int size,id;
}*root,que[maxn];
int tot;
int val[maxn];
int n,m;
char str[30000],s[30];
ll ans;
inline int idx(char s)
{
    return s-'a';
}
void insert(char*s,int rank=1)
{
    node *rt;
    node *nxt;
    for(rt=root; *s; rt=nxt,++s)
    {
        nxt=rt->go[idx(*s)];
        if (nxt==NULL)
        {
            nxt=&que[tot];
            nxt->id=tot;
            for (int i=0; i<S; i++)
            nxt->go[i]=NULL;
            nxt->size=1;
            tot++;
            rt->go[idx(*s)]=nxt;
        }
        else nxt->size++;
    }
    val[rt->id]=rank;
}
int tt;
int main()
{
//    freopen("in.txt","r",stdin);


    root=&que[0];
    tot=1;
        while(true)
        {
            gets(str);
            if (!str[0]) break;
            insert(str);
        }
        node* rt=root;
        int res;
        while(~scanf("%s",str))
        {
            int len=strlen(str);
            rt=root;
            for (int i=0; i<len; i++)
            {
                if (rt->go[idx(str[i])]==NULL)
                {
                    res=0;
                    break;
                }
                rt=rt->go[idx(str[i])];
                res=rt->size;
            }
            printf("%d\n",res);
        }

    return 0;
}