kuangbin巨的专题实在搞不懂了,里面一大堆dp,实在不会写,正好找到了这道题,模板也是终于加上了注释
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1277
题意:就是给你一大~大串数字,再给你几串数字,按照在主串中出现的先后顺序输出序号
思路:直接AC自动机查询不解释,有一个问题是我们要做到按出现的先后顺序输出,这道题与HDU 2896很相似,那道题是查询完之后,依次输出查找成功的(true), 这道题我们可以直接在每次查找成功时,就输出,因为按照Trie图来说, 先找到的也一定在主串中先出现。还有一个问题是,输入的问题,scanf(s)不接受空格, 然后就是我们不能够像以前一样,输入一个子串查询一次了,这次我们要统一查询,在输入时将子串连在一起就好了
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10;
char str[60005];
int idx(char c){return c - '0';}
struct Trie
{
int next[10000*65][maxn];
int fail[10000*65]; //失配指针
int last[10000*65]; //记录数组
int root; //根结点指针
int L; //总长度
int newnode() //获取新结点并初始化
{
for(int i = 0; i < maxn; i++) next[L][i] = -1;
last[L] = -1;
return L++;
}
void init() //初始化
{
L = 0;
root = newnode();
}
void insert(char s[],int id)
{
int len = strlen(s), now = root;
for(int i = 0; i < len; i++){
int c = idx(s[i]);
if(next[now][c] == -1) //不存在该结点
next[now][c] = newnode();
now = next[now][c];
}
last[now]=id; //记录其id
}
void Build()
{
queue<int> q;
fail[root] = root; //根结点失配指针指向自己
//根结点的孩子入队,其失配指针指向自己
for(int i = 0; i < maxn; i++){
if(next[root][i] == -1) //不存在该孩子
next[root][i] = root; //指向自己
else{
fail[next[root][i]] = root; //失配指针指向自己
q.push(next[root][i]); //孩子入队
}
}
while(!q.empty()){
int now = q.front();
q.pop();
for(int i = 0; i < maxn; i++){
if(next[now][i] == -1) //不存在该孩子,指向其父结点失配指针所指向的结点(该结点也有孩子i)
next[now][i] = next[fail[now]][i];
else{
fail[next[now][i]] = next[fail[now]][i];
q.push(next[now][i]);
}
}
}
}
bool used[10001];
void query(char buf[])
{
int len = strlen(buf), now = root;
memset(used, 0, sizeof(used));
bool flag = false;
for(int i = 0; i < len; i++){
now = next[now][buf[i]-'0'];
int temp = now;
while(temp != root)
{
if(last[temp] != -1){ //该单词或字符在Trie中出现了
used[last[temp]] = 1;
if(!flag){
printf("Found key:" );
flag = true;
}
printf(" [Key No. %d]", last[temp] );
}
temp = fail[temp]; //继续找后缀串
}
}
if(!flag) puts( "No key can be found !" );
else printf("\n");
}
}trie;
char temp[100];
int main()
{
int n,m,len,id;
while (~scanf("%d %d", &m, &n)){
getchar();
trie.init();
memset(str, 0, sizeof(str));
for (int i = 1; i <= m; i++){
gets(temp);
strcat(str, temp);
}
getchar();
for (int i = 1; i <= n; i++){
scanf("[Key No. %d] ", &id );
gets(temp);
trie.insert(temp, id);
}
trie.Build();
trie.query(str);
}
return 0;
}