HDU 1277

HDU 1277 全文检索

题意

给定一个很长的字符串,因为很长所以分成很多行,全为数字组成,不少于60个,不多于60000个。
然后给定一些需要检索的串,个数不超过10000个,每个串长度不超过60。问哪些串出现在文本串中。

思路

知道是字典树,但不知道怎么建树,也不知道从哪里入手,之后看题解才发现是让检索的串形成一棵树,然后从文本串的每一位开始遍历,然后每次遍历字典树最多只有O(60),总的时间复杂度为O(60*60000)

代码

#include <iostream>
#include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <map>
#include <set>
#define  int long long 
#define endl "\n"
#define pii pair<int,int>
using namespace std;
typedef unsigned long long ull;
const int mod=1e9+7,N=2e6+10,M=1e4+10,inf=1e18;
int n,m;
int son[N][10],ed[N],idx,flag,len;
string str,s,tmp;

void insert(string s,int id) 
{
	int p=0;
	for(int i=0;s[i];i++) 
	{
		int c = s[i]-'0';
		if(!son[p][c]) son[p][c]=++idx;
		p=son[p][c];
	}
	ed[p]=id;
}

void fd(int be) 
{	
	int p=0;
	for(int i=be;str[i];i++) 
	{
		int c=str[i]-'0';
		if(ed[p]) 
		{
			if(flag==0) 
			{
				cout<<"Found key:";
				flag=1;
			}
			cout<<" [Key No. "<<ed[p]<<"]";
			ed[p]=0;
		}
		if(!son[p][c]) return;
		p=son[p][c];
	}
}

void solve()
{	
	flag=0;
	cin>>n>>m;
	for(int i=1;i<=n;i++) 
	{
		cin>>tmp;
		str=str+tmp;
	}
	for(int i=1;i<=m;i++) 
	{
		cin>>tmp>>tmp>>tmp>>s;
		//因为读入是[Key No. 1] 数字串
		//为了过滤掉前面的那些字符 
		insert(s,i);
	}
	for(int i=0;str[i];i++) 
	{
		fd(i);
	}
	if(flag==0) cout<<"No key can be found !"<<endl;
	else cout<<endl;
}

signed main()
{	
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
	//cin>>t;
	while(t--) solve();
	return 0;
}
posted @ 2023-02-16 09:26  Liang2003  阅读(11)  评论(0编辑  收藏  举报