[uva][4657][Top 10]

题目:http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2658

ac自动机。先把单词按照题意排序,把询问串建成trie树,然后按照单词顺序进行查询,注意好结果保存,询问串可能会有重复。

View Code
#include <cstdio>

#include <cstring>

#include <string>

#include <vector>

#include <iostream>

#include <algorithm>



#define clr(a,b) memset(a,b,sizeof(a))

using namespace std;



const int N = 1000000+10;

const int M = 10001 * 50;

const int ch = 26;

int sw[128];

int trie[M][ch+1], top, n, q[M], bg, ed, fail[M];

bool vis[M];

char str[N];

vector<int>ans[N], tim[N];

struct acstr

{

    int id;

    string s;

    void get(int i){ id=i; gets(str); s=str;}

    bool operator < (const acstr& a)const{

        if (s.length()==a.s.length()){

            if (s == a.s)return id < a.id;

            return s < a.s;

        }

        return s.length() < a.s.length();

    }

}buf[20010];



void init(){

    top = 1; clr(trie[0], 0);

    for (char i='a', j=0; i<='z'; i++, j++)

        sw[i] = j;

}

void ins(char *s, int rank){

    int rt, nxt;

    for (rt=0; *s; rt=nxt, s++){

        nxt = trie[rt][sw[*s]];

        if (nxt == 0){

            clr(trie[top], 0); trie[rt][sw[*s]]=nxt=top++;

        }

    }

    tim[rt].push_back(rank);   // 保存该点id,不能直接覆盖,可能会有重复

}

void makefail(){

    int u, v;

    fail[0] = bg = ed = 0;

    for (int i=0; i<ch; i++)

        if (q[ed] = trie[0][i])

            fail[q[ed++]] = 0;

    while (bg < ed){

        u = q[bg++];

        for (int i=0; i<ch; i++){

            if (v = trie[u][i])

                q[ed++]=v, fail[v]=trie[fail[u]][i];

            else

                trie[u][i] = trie[fail[u]][i];

        }

    }

}

void ac(const char *s, int id){

    clr(vis, 0);

    for (int i=0; *s; s++){

        i=trie[i][sw[*s]];

        for (int j=i,v; j; j=fail[j]){

            for (int k=0; k<tim[j].size(); k++){  

                v=tim[j][k];

                if(vis[v])continue;

                vis[v] = true;

                if (ans[v].size()<10)ans[v].push_back(id);

            }

        }

    }

}

char tmp[20010];

int main(){

    //freopen("D:/a.txt", "r", stdin);

    int n, q;

    while (~scanf("%d", &n)){

        init(); getchar();

        for (int i=1; i<=n; i++)

            buf[i].get(i);

        sort(buf+1, buf+1+n);

        scanf("%d", &q);

        for (int i=1; i<=q; i++){

            scanf("%s", tmp); ins(tmp, i);

        }

        makefail();

        for (int i=1; i<=n; i++) ac(buf[i].s.c_str(),buf[i].id);

        for (int i=1; i<=q; i++){

            if (ans[i].size()==0)printf("-1\n");

            else for (int j=0; j<ans[i].size(); j++)

                printf("%d%c", ans[i][j], j==ans[i].size()-1?'\n':' ');

        }

    }

    return 0;

}

你可能感兴趣的:(top)