前綴統計 [Trie]

前綴統計

描述

給定N個字符串S1,S2...SN,接下來進行M次詢問,每次詢問給定一個字符串T,求S1~SN中有多少個字符串是T的前綴。輸入字符串的總長度不超過10^6,僅包含小寫字母。ios

輸入格式

第一行兩個整數N,M。接下來N行每行一個字符串Si。接下來M行每行一個字符串表示詢問。spa

輸出格式

對於每一個詢問,輸出一個整數表示答案code

樣例輸入

3 2
ab
bc
abc
abc
efgblog

樣例輸出

2
0字符串

題解

trie樹操做,把這n個字符串插入到trie中,並更新一下節點信息
在這道題中,每一個節點只須要保存cnt表示當前節點是多少個字符串的末尾節點,那麼若是被詢問的字符串T匹配到當前節點,表示從T的首字符開始到當前一直是匹配的,那麼咱們在查詢過程當中累加節點的cnt值就能夠了
中間注意判斷一下,若是trie已經搜到了葉子節點還要但匹配尚未完成,直接return ansget

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define Min(a,b) (a)<(b)?(a):(b)
#define Max(a,b) (a)>(b)?(a):(b)
#define in(i) (i=read())
using namespace std;
int read() {
    int ans=0,f=1; char i=getchar();
    while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
    while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+i-'0'; i=getchar();}
    return ans*f;
}
int n,m,tot;
int trie[1000010][27],cnt[1000010];
void insert(char* str) {
    int len=strlen(str),p=0;
    for(int i=0;i<len;i++) {
        int ch=str[i]-'a';
        if(!trie[p][ch]) trie[p][ch]=++tot;
        p=trie[p][ch];
    }
    cnt[p]++;
}
int search(char* str) {
    int ans=0;
    int len=strlen(str),p=0;
    for(int i=0;i<len;i++) {
        int ch=str[i]-'a';
        p=trie[p][ch];
        if(!p) return ans;
        ans+=cnt[p];
    }
    return ans;
}
int main()
{
    char s[1000010];
    in(n); in(m);
    for(int i=1;i<=n;i++) {
        scanf("%s",s); insert(s);
    }
    for(int i=1;i<=m;i++) {
        scanf("%s",s);
        printf("%d\n",search(s));
    }
    return 0;
}

博主蒟蒻,隨意轉載.但必須附上原文連接

http://www.cnblogs.com/real-l/

相關文章
相關標籤/搜索