词典 Trie字典树模板题

词典
Description
小C有n个字符串T1…Tn,给出n个询问
第i个询问给出一个字符串Si,对于每个询问,我们可以得到一个长度为n的bool数组a,其中ai=[Si是否为Ti的前缀]
例如,a=[0,0,1]表示Si是T3的前缀,但不是T1,T2的前缀。
对于每个询问给出的a数组,你的任务是求出它的最长全0子串长度
Input
第一行两个数n,m,表示有n个字符串,m个询问。
接下来n行,每行一个字符串Ti。
再接下来m行,每行一个字符串Si。
Output
对于每个询问,输出一个ansi表示答案。
Sample Input
3 2
abcabc
aabc
abbc
aa
ba
Sample Output
1
3
Data Constraint
对于10%的数据,n≤10^2,m≤10^2,len Ti ≤ 10^2,Σlen Si ≤10^3
对于30%的数据,n≤10^3,m≤10^3,len Ti ≤ 10^3,Σlen Si ≤10^4
对于100%的数据,n≤10^5,m≤10^5,Σlen Ti ≤ 5×10^6,Σlen Si ≤3×10^6,字符串中只包含a,b,c三种字母,数据随机

首先,观察题目,容易看出来,题目的大意是,首先给我们n个字符串,接下来,有m个询问。
对于每个询问,都有一个字符串Si,询问Si是否是先前n个字符串的前缀,并输出连续的最多Si不是该字符串前缀的字符串的个数。
换言之,就是查找匹配成功字符串(也就是Si是该字符串的前缀)之间的最多有多少个字符串。
其实,我们可以转换一下概念,把字符串Ti的所有前缀都标记为i(包括Ti本身),而下一次查找的过程中,发现这个前缀已经被标记为i,就比较此时应标记的编号与上一次搜索时的编号的差和此时标记值i对比,判断是否更新i的值。
这样,我们就可以直接搜索字符串Si,找到与它相等的字符串(可能是Ti本身,也可能是Ti的前缀),然后就可以直接得到标记值i,而i就是我们要求的”最长全0子串长度”。
当然,不要忘了,如果此时该字符串最后更新的编号是a,它后面还有n-a长度的”最长全0字串”,再进行一次比较就可以得到ansi了。

代码如下

#include 
#include 

using namespace std;

struct node{
    int to,ans,next;
}t[5000010][3];
int n,m,tot;

void addtrie(int );
void find();

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        addtrie(i);
    for (int i=1;i<=m;i++)
        find();
    return 0;
}

void addtrie(int i)
{
    char c=getchar();
    while ((c<'a')||(c>'c'))
        c=getchar();
    int j=0;
    while ((c>='a')&&(c<='c'))
    {
        if (t[j][c-'a'].to)
            t[j][c-'a'].ans=max(t[j][c-'a'].ans,i-t[j][c-'a'].next-1);
        else
        {
            t[j][c-'a'].ans=i-1;
            t[j][c-'a'].to=++tot;
        }
        t[j][c-'a'].next=i;
        j=t[j][c-'a'].to;
        c=getchar();
    }
    return ;
}

void find()
{
    char c=getchar();
    while ((c<'a')||(c>'c'))
        c=getchar();
    int j=0;
    int an;
    while ((c>='a')&&(c<='c'))
    {
        an=max(t[j][c-'a'].ans,n-t[j][c-'a'].next);
        if (!t[j][c-'a'].to)
        {
            printf("%d\n",n);
            while ((c>='a')&&(c<='c'))
                c=getchar();
            return ;
        }
        j=t[j][c-'a'].to;
        c=getchar();
    }
    printf("%d\n",an);
    return ;
}

你可能感兴趣的:(词典 Trie字典树模板题)