HDU 6096 String (字典树, 2017 Multi-Univ Training Contest 6)

Problem

有 N 组单词 Wi ,以及 Q 组前缀 Pi ,后缀 Si 。求对于每组前后缀,能匹配多少单词。

Idea

利用字典树解决。将前缀与后缀拼接形成 Pi++reverse(Si) 。并离线将全部询问加入字典树中,在最后一个节点位置标记上该点标号。

枚举每个单词,查找单词在字典树上能有多少的匹配情况。具体为:优先匹配 Wi 在字典树的前缀,当有某点的后继节点存在 拼接符 ,则倒置 Wi 开始匹配后缀,对找到的每个标记 ++ 。

Code

#include
using namespace std;
const int N = 500000 + 10;
int T, n, Q, st[N], len[N], pot[N], ans[N];
char s[N], pre[N], suf[N], combin[N];
const int Node_max = 1000000 + 5;
struct Node{
    int next[30], flag;
} Trie[Node_max];
int Tsize;
int Trie_insert(char str[], int st, int len, int idx){
    int tmp = 0;
    for(int i=st;iif(!Trie[tmp].next[str[i] - 'a']) {
            Trie[tmp].next[str[i] - 'a'] = ++Tsize;
        }
        tmp = Trie[tmp].next[str[i]-'a'];
    }
    if(Trie[tmp].flag == 0) Trie[tmp].flag = idx;
    return Trie[tmp].flag;
}
void Trie_query_suf(int it, int st, int en) {
    for(int i=en;i>=st;i--) {
        if(Trie[it].next[s[i] - 'a'] == 0)  return;
        it = Trie[it].next[ s[i] - 'a' ];
        if(Trie[it].flag)   ans[ Trie[it].flag ]++;
    }
}
void Trie_query_pre(int it, int st, int en) {
    for(int i=st;i<=en;i++) {
        if(Trie[it].next[26])   Trie_query_suf(Trie[it].next[26], i, en);
        if(Trie[it].next[ s[i] - 'a' ] == 0)    return;
        it = Trie[it].next[ s[i] - 'a' ];
    }
}

int main()
{
    scanf("%d", &T);
    while(T-- && scanf("%d %d", &n, &Q)!=EOF)
    {
        memset(Trie, 0, sizeof(Trie));
        memset(ans, 0, sizeof(ans));
        Tsize = 0;
        int ip = 0;
        for(int i=1;i<=n;i++) {
            scanf(" %s", s+ip);
            st[i] = ip;
            len[i] = strlen(s+ip);  
            ip += len[i];
        }

        for(int i=1;i<=Q;i++) {
            scanf(" %s %s", pre, suf);
            int qlen = 0;
            for(;pre[ qlen ];qlen++)
                combin[qlen] = pre[qlen];
            combin[qlen++] = char('z'+1);
            for(int j=strlen(suf)-1;j>=0;j--)
                combin[qlen++] = suf[j];
            combin[qlen] = '\0';
            pot[i] = Trie_insert(combin, 0, qlen, i);   
        }

        for(int i=1;i<=n;i++) {
            Trie_query_pre(0, st[i], st[i]+len[i]-1);
        }

        for(int i=1;i<=Q;i++) {
            if(pot[i] != i) ans[i] = ans[ pot[i] ];
            printf("%d\n", ans[i]);
        }
    }
}

你可能感兴趣的:(HDU,Multi-Univ)