洛谷2292 HNOI2004 L语言

题目:


思路:trie+dp。先将所有单词 倒着 存进字典树,val为单词的长度。对于每一篇文章,bool f[i] 表示前i个字符能否被破解。其中如果前i个字母构成的字符串的后缀中有在字典树中存在的单词,则只需要看这篇文章去掉单词后缀后剩下的前面一段能否被破解。也就是说 只要存在任意 j,使得 f[ i - val[ j ] ] = true,那么 f[i]=true。最后只需找到最大的i使得 f[i]==true输出即可。


注意:我之前写了一支程序最后一个点TLE了,然后把一个返回vector的函数删了就好了。看来vector这种东西还是不能随便用。


代码:

#include<iostream>
#include<cstdio>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
using namespace std;

#define maxn 20
#define maxw 10
#define maxl 1000000

struct Trie {
	int ch[maxn*maxw+5][30];
	int val[maxn*maxw+5];
	int sz;
	bool f[maxl+5];

	Trie() {
		memset(ch,0,sizeof(ch));
		memset(val,0,sizeof(val));
		sz=0;
	}

	void insert(char* x,int len) {
		int u=0;
		for(int i=len-1; i>=0; i--) {
			int y=x[i]-'a';
			if(!ch[u][y]) {
				ch[u][y]=++sz;
			}
			u=ch[u][y];
		}
		val[u]=len;
	}

	vector<int> find(char* x,int i) {
		int u=0;
		vector<int> vec;
		for(int j=i; j>=0; j--) {
			int y=x[j]-'a';
			if(!ch[u][y]) return vec;
			u=ch[u][y];
			if(val[u]) vec.push_back(val[u]);
		}
	}

	int query(char* x,int len) {
		memset(f,0,sizeof(f));
		f[0]=1;
		for(int i=0; i<len; i++) {
			int u=0;
			for(int j=i; j>=0; j--) {
				int y=x[j]-'a';
				if(!ch[u][y]) break;
				u=ch[u][y];
				if(val[u]) {
					if(f[i+1-val[u]]) f[i+1]=1;
				}
			}
		}

		for(int i=len; i>=1; i--) {
			if(f[i]) return i;
		}

		return 0;
	}
};

int n,m;
Trie trie;

int main() {

	scanf("%d%d",&n,&m);

	for(int i=0; i<n; i++) {
		char x[maxw+5];
		scanf("%s",x);
		trie.insert(x,strlen(x));
	}

	for(int i=0; i<m; i++) {
		char x[maxl+5];
		scanf("%s",x);
		printf("%d\n",trie.query(x,strlen(x)));
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值