[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;
}
原文地址:https://www.cnblogs.com/nigel0913/p/2592196.html